defuss-morph 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/README.md +281 -218
- package/dist/all.js +454 -200
- package/dist/all.js.map +15 -11
- package/dist/all.min.js +1 -1
- package/dist/all.min.js.map +1 -1
- package/dist/index.cjs +344 -121
- package/dist/index.d.ts +308 -26
- package/dist/index.mjs +334 -122
- package/dist/stats.json +9 -9
- package/package.json +46 -13
- package/skills/defuss-morph/SKILL.md +101 -0
- package/skills/defuss-morph/references/api.md +86 -0
- package/skills/defuss-morph/references/integrations.md +116 -0
- package/skills/defuss-morph/references/patterns.md +190 -0
- package/skills/defuss-morph/references/pitfalls.md +29 -0
package/dist/all.js.map
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/queue.ts", "../src/delegated-events.ts", "../src/html.ts", "../src/renderer.ts", "../src/morph.ts", "../src/transitions.ts", "../src/
|
|
3
|
+
"sources": ["../src/queue.ts", "../src/delegated-events.ts", "../src/html.ts", "../src/renderer.ts", "../src/lis.ts", "../src/morph.ts", "../src/transitions.ts", "../src/api.ts", "../src/jsx.ts", "../src/ref.ts", "../src/reactive.ts", "../src/global.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"
|
|
6
|
-
"export type DelegatedPhase = \"bubble\" | \"capture\";\n\nexport interface DelegatedEventOptions {\n capture?: boolean;\n /** If true, allows multiple handlers per element+type (Dequery mode) */\n multi?: boolean;\n}\n\nexport interface ParsedEventProp {\n eventType: string;\n capture: boolean;\n}\n\n/**\n * Events whose handlers are forced into the capture phase, so an ancestor's\n * handler also sees descendants' events (container onFocus/onBlur). Every\n * other non-bubbling event reaches only its target's handlers, natively.\n */\nexport const CAPTURE_ONLY_EVENTS = new Set<string>([\n \"focus\",\n \"blur\",\n \"scroll\",\n \"mouseenter\",\n \"mouseleave\",\n // Note: focusin/focusout DO bubble, so they're not included here\n]);\n\n/**\n * Why per-element native listeners instead of one delegating root listener:\n * replaying the event path from the document ran handlers in the wrong order\n * relative to native listeners, ignored an ancestor's stopPropagation(), missed\n * non-bubbling events and reported currentTarget === document. On the element\n * itself the browser applies every propagation rule exactly.\n * VERIFIED: order, stopPropagation (both phases), stopImmediatePropagation,\n * currentTarget, non-bubbling and shadow DOM (delegated-events.browser.test.ts).\n *\n * What stays \"delegated\" is the indirection: a JSX prop slot owns one\n * trampoline listener that calls whichever handler the slot holds right now,\n * so re-renders swap handlers without touching listeners. Multi-mode handlers\n * (dequery-style on()) are attached as-is.\n */\ninterface HandlerEntry {\n bubble?: EventListener;\n capture?: EventListener;\n bubbleSet?: Set<EventListener>;\n captureSet?: Set<EventListener>;\n}\n\n/** element -> (eventType -> handlers) */\nconst elementHandlerMap = new WeakMap<EventTarget, Map<string, HandlerEntry>>();\n\n/** element -> (`${eventType}:${phase}` -> installed slot trampoline) */\nconst slotListeners = new WeakMap<EventTarget, Map<string, EventListener>>();\n\n/**\n * Re-entrancy guard for JSX slots: while a slot's handler runs, a *new* event\n * of the same type that morph fires synchronously on the same element (e.g.\n * focus/blur while moving nodes) does not re-enter it.\n */\nconst activeDispatches = new WeakMap<EventTarget, Set<string>>();\n\nexport const parseEventPropName = (\n propName: string,\n): ParsedEventProp | null => {\n if (!propName.startsWith(\"on\")) return null;\n\n // support onClick / onClickCapture / onclick / onclickcapture\n const raw = propName.slice(2);\n if (!raw) return null;\n\n const lower = raw.toLowerCase();\n const isCapture = lower.endsWith(\"capture\");\n\n const eventType = isCapture ? lower.slice(0, -\"capture\".length) : lower;\n\n if (!eventType) return null;\n\n return { eventType, capture: isCapture };\n};\n\nconst getOrCreateElementHandlers = (el: EventTarget) => {\n const existing = elementHandlerMap.get(el);\n if (existing) return existing;\n\n const created = new Map<string, HandlerEntry>();\n elementHandlerMap.set(el, created);\n return created;\n};\n\n/** Run the handler a JSX slot holds right now (looked up per event). */\nconst runSlot = (\n target: EventTarget,\n eventType: string,\n phase: DelegatedPhase,\n event: Event,\n): void => {\n const handler = elementHandlerMap.get(target)?.get(eventType)?.[phase];\n if (!handler) return;\n\n const dispatchKey = `${eventType}:${phase}`;\n let active = activeDispatches.get(target);\n if (active?.has(dispatchKey)) return;\n if (!active) {\n active = new Set();\n activeDispatches.set(target, active);\n }\n active.add(dispatchKey);\n try {\n handler.call(target, event);\n } finally {\n active.delete(dispatchKey);\n }\n};\n\n/** Set (or clear) a JSX slot, installing/removing its trampoline listener. */\nconst setSlot = (\n target: EventTarget,\n eventType: string,\n phase: DelegatedPhase,\n entry: HandlerEntry,\n handler: EventListener | undefined,\n): void => {\n entry[phase] = handler;\n const key = `${eventType}:${phase}`;\n const capture = phase === \"capture\";\n let byKey = slotListeners.get(target);\n const installed = byKey?.get(key);\n\n if (handler && !installed) {\n if (!byKey) {\n byKey = new Map();\n slotListeners.set(target, byKey);\n }\n const trampoline: EventListener = (event) =>\n runSlot(target, eventType, phase, event);\n byKey.set(key, trampoline);\n target.addEventListener(eventType, trampoline, capture);\n } else if (!handler && installed) {\n byKey!.delete(key);\n target.removeEventListener(eventType, installed, capture);\n }\n};\n\n/** Detach every handler of one phase (slot and set) for a type. */\nconst clearPhase = (\n target: EventTarget,\n eventType: string,\n entry: HandlerEntry,\n phase: DelegatedPhase,\n): void => {\n setSlot(target, eventType, phase, entry, undefined);\n const setKey = phase === \"capture\" ? \"captureSet\" : \"bubbleSet\";\n for (const handler of entry[setKey] ?? [])\n target.removeEventListener(eventType, handler, phase === \"capture\");\n entry[setKey] = undefined;\n};\n\nexport const registerDelegatedEvent = (\n element: HTMLElement,\n eventType: string,\n handler: EventListener,\n options: DelegatedEventOptions = {},\n): void => {\n // capture-only events should be forced to capture\n const capture = options.capture || CAPTURE_ONLY_EVENTS.has(eventType);\n const phase: DelegatedPhase = capture ? \"capture\" : \"bubble\";\n\n const byEvent = getOrCreateElementHandlers(element);\n const entry = byEvent.get(eventType) ?? {};\n byEvent.set(eventType, entry);\n\n if (options.multi) {\n // Dequery mode: every handler is its own native listener (the set mirrors\n // addEventListener's dedupe of an identical type/handler/capture triple)\n const setKey = capture ? \"captureSet\" : \"bubbleSet\";\n const set = (entry[setKey] ??= new Set());\n if (!set.has(handler)) {\n set.add(handler);\n element.addEventListener(eventType, handler, capture);\n }\n } else {\n // JSX mode: one handler per prop, overwrite to prevent duplicates\n setSlot(element, eventType, phase, entry, handler);\n }\n};\n\n/** true when a handler entry holds no single handler and no non-empty set */\nconst isEntryEmpty = (entry: HandlerEntry): boolean =>\n !entry.capture &&\n !entry.bubble &&\n (!entry.captureSet || entry.captureSet.size === 0) &&\n (!entry.bubbleSet || entry.bubbleSet.size === 0);\n\nexport const removeDelegatedEvent = (\n target: EventTarget,\n eventType: string,\n handler?: EventListener,\n // part of the public signature; removal always covers both phases,\n // so the options are intentionally not consulted here\n _options: DelegatedEventOptions = {},\n): void => {\n const byEvent = elementHandlerMap.get(target);\n if (!byEvent) return;\n\n const entry = byEvent.get(eventType);\n if (!entry) return;\n\n if (handler) {\n // Remove the specific handler from both phases (the caller may not know which)\n for (const phase of [\"capture\", \"bubble\"] as const) {\n const set = phase === \"capture\" ? entry.captureSet : entry.bubbleSet;\n if (set?.delete(handler))\n target.removeEventListener(eventType, handler, phase === \"capture\");\n if (entry[phase] === handler)\n setSlot(target, eventType, phase, entry, undefined);\n }\n } else {\n // Remove ALL handlers for this event type (both phases)\n // This is what users expect from .off(\"click\") without specific handler\n clearPhase(target, eventType, entry, \"capture\");\n clearPhase(target, eventType, entry, \"bubble\");\n }\n\n // Clean up entry if empty\n if (isEntryEmpty(entry)) {\n byEvent.delete(eventType);\n }\n};\n\n/** Teardown hooks of listener owners outside this registry. */\nconst clearHooks = new Set<(target: EventTarget) => void>();\n\n/**\n * Why: listeners a facade attaches natively (defuss-query's on()) live\n * outside this registry, yet must go whenever morph clears an element\n * (removal, replacement, clearDelegatedEventsDeep). A hook keeps morph\n * ignorant of who owns them, instead of morph also tracking native listeners.\n * Registering the same hook twice is a no-op; returns an unregister function.\n */\nexport const onClearDelegatedEvents = (\n hook: (target: EventTarget) => void,\n): (() => void) => {\n clearHooks.add(hook);\n return () => {\n clearHooks.delete(hook);\n };\n};\n\nexport const clearDelegatedEvents = (target: EventTarget): void => {\n const byEvent = elementHandlerMap.get(target);\n if (byEvent) {\n for (const [eventType, entry] of byEvent) {\n clearPhase(target, eventType, entry, \"capture\");\n clearPhase(target, eventType, entry, \"bubble\");\n }\n byEvent.clear();\n }\n for (const hook of clearHooks) hook(target);\n};\n\n/**\n * Clear delegated events for an element and all its descendants.\n * Used by empty() to prevent event handler leaks when removing subtrees.\n */\nexport const clearDelegatedEventsDeep = (root: HTMLElement): void => {\n // Clear the root element\n clearDelegatedEvents(root);\n\n // Walk all descendant elements and clear their handlers\n // Use ownerDocument for SSR/multi-doc compatibility\n const doc = root.ownerDocument;\n if (!doc) return;\n const walker = doc.createTreeWalker(root, 1 /* NodeFilter.SHOW_ELEMENT */);\n let node = walker.nextNode();\n while (node) {\n clearDelegatedEvents(node as HTMLElement);\n node = walker.nextNode();\n }\n};\n\n/**\n * Get all event types currently registered on an element.\n * Used to detect which events need to be removed when vnode props change.\n */\nexport const getRegisteredEventTypes = (element: HTMLElement): Set<string> => {\n const byEvent = elementHandlerMap.get(element);\n if (!byEvent) return new Set();\n return new Set(byEvent.keys());\n};\n\n/**\n * Get all event keys with phases currently registered on an element.\n * Returns keys like \"click:bubble\", \"click:capture\" for precise phase-aware removal.\n */\nexport const getRegisteredEventKeys = (element: HTMLElement): Set<string> => {\n const byEvent = elementHandlerMap.get(element);\n if (!byEvent) return new Set();\n\n const keys = new Set<string>();\n for (const [eventType, entry] of byEvent) {\n if (entry.bubble || entry.bubbleSet?.size) keys.add(`${eventType}:bubble`);\n if (entry.capture || entry.captureSet?.size)\n keys.add(`${eventType}:capture`);\n }\n return keys;\n};\n\n/**\n * Remove delegated event handler for a specific phase only.\n * Used by patchElementInPlace to precisely remove stale handlers when vnode changes from\n * onClick + onClickCapture → onClickCapture only.\n */\nexport const removeDelegatedEventByKey = (\n element: HTMLElement,\n eventType: string,\n phase: \"bubble\" | \"capture\",\n): void => {\n const byEvent = elementHandlerMap.get(element);\n if (!byEvent) return;\n\n const entry = byEvent.get(eventType);\n if (!entry) return;\n\n clearPhase(element, eventType, entry, phase);\n\n // Clean up entry if empty\n if (isEntryEmpty(entry)) byEvent.delete(eventType);\n};\n",
|
|
7
|
-
"import type { VNode, VNodeAttributes } from \"./types.js\";\n\n/**\n * Marks VNodes derived from existing DOM (HTML strings / DOM nodes).\n * Such VNodes cannot declare event handlers, so the morph engine must\n * preserve delegated handlers already attached to surviving elements\n * (same rationale as uncontrolled form-state preservation).\n */\nexport const FROM_DOM_MARKER: unique symbol = Symbol(\"defuss-morph.from-dom\");\n\n/**\n * VNode type of an HTML comment: `{ type: \"#comment\", value }`.\n * Why \"#comment\": it is the DOM's own nodeName for comments and can never\n * collide with a tag name (\"#\" is invalid there). The data lives in `value`,\n * not `children`, so generic tree walkers never mistake it for content.\n */\nexport const COMMENT_TYPE = \"#comment\";\n\nexport type CommentVNode = VNode & { type: typeof COMMENT_TYPE };\n\nexport const isCommentVNode = (value: unknown): value is CommentVNode =>\n !!value &&\n typeof value === \"object\" &&\n (value as VNode).type === COMMENT_TYPE;\n\nconst HTML_BOOLEAN_ATTRIBUTES = new Set([\n \"allowfullscreen\",\n \"async\",\n \"autofocus\",\n \"autoplay\",\n \"checked\",\n \"controls\",\n \"default\",\n \"defer\",\n \"disabled\",\n \"formnovalidate\",\n \"hidden\",\n \"inert\",\n \"ismap\",\n \"itemscope\",\n \"loop\",\n \"multiple\",\n \"muted\",\n \"nomodule\",\n \"novalidate\",\n \"open\",\n \"playsinline\",\n \"readonly\",\n \"required\",\n \"reversed\",\n \"selected\",\n]);\n\nconst domAttributeToVNodeValue = (attr: Attr): string | boolean =>\n HTML_BOOLEAN_ATTRIBUTES.has(attr.name.toLowerCase()) ? true : attr.value;\n\nexport function parseDOM(\n input: string,\n type: DOMParserSupportedType,\n Parser: typeof DOMParser,\n): Document {\n return new Parser().parseFromString(input, type);\n}\n\nexport function isSVG(input: string, Parser: typeof DOMParser) {\n const doc = parseDOM(input, \"image/svg+xml\", Parser);\n if (!doc.documentElement) return false;\n return doc.documentElement.nodeName.toLowerCase() === \"svg\";\n}\n\nexport function isHTML(input: string, Parser: typeof DOMParser): boolean {\n const doc = parseDOM(input, \"text/html\", Parser);\n return doc.documentElement.querySelectorAll(\"*\").length > 2; // 2 = <html> and <body>\n}\n\nexport const isMarkup = (input: string, Parser: typeof DOMParser): boolean =>\n input.indexOf(\"<\") > -1 &&\n input.indexOf(\">\") > -1 &&\n (isHTML(input, Parser) || isSVG(input, Parser));\n\nexport function renderMarkup(\n markup: string,\n Parser: typeof DOMParser,\n doc?: Document,\n) {\n const parsed = doc ? doc : parseDOM(markup, getMimeType(markup, Parser), Parser);\n // HTML documents expose body; XML documents (e.g. image/svg+xml) don't —\n // there the documentElement is the root node to render\n if (parsed.body) return Array.from(parsed.body.childNodes);\n return parsed.documentElement ? [parsed.documentElement] : [];\n}\n\nexport function getMimeType(\n input: string,\n Parser: typeof DOMParser,\n): DOMParserSupportedType {\n if (isSVG(input, Parser)) {\n return \"image/svg+xml\";\n }\n return \"text/html\";\n}\n\n/**\n * Converts a DOM node to a VNode structure for use with updateDomWithVdom.\n * This allows us to leverage the sophisticated partial update system even for Node inputs.\n */\nexport function domNodeToVNode(node: Node): VNode<VNodeAttributes> | string {\n if (node.nodeType === 3 /* Node.TEXT_NODE */) {\n return node.
|
|
8
|
-
"import type {\n DomAbstractionImpl,\n RenderInput,\n VNode,\n VNodeAttributes,\n VNodeChildren,\n} from \"./types.js\";\nimport { queueCallback } from \"./queue.js\";\nimport {\n parseEventPropName,\n registerDelegatedEvent,\n} from \"./delegated-events.js\";\nimport { isCommentVNode } from \"./html.js\";\n\nexport const CLASS_ATTRIBUTE_NAME = \"class\";\nexport const XLINK_ATTRIBUTE_NAME = \"xlink\";\nexport const XMLNS_ATTRIBUTE_NAME = \"xmlns\";\nexport const REF_ATTRIBUTE_NAME = \"ref\";\nexport const DANGEROUSLY_SET_INNER_HTML_ATTRIBUTE = \"dangerouslySetInnerHTML\";\n\nexport const nsMap = {\n [XMLNS_ATTRIBUTE_NAME]: \"http://www.w3.org/2000/xmlns/\",\n [XLINK_ATTRIBUTE_NAME]: \"http://www.w3.org/1999/xlink\",\n svg: \"http://www.w3.org/2000/svg\",\n};\n\nexport const observeUnmount = (domNode: Node, onUnmount: () => void): void => {\n if (!domNode || typeof onUnmount !== \"function\") {\n throw new Error(\n \"Invalid arguments. Ensure domNode and onUnmount are valid.\",\n );\n }\n\n // Skip MutationObserver in SSR environments where it doesn't exist\n if (typeof MutationObserver === \"undefined\") {\n return;\n }\n\n let parentNode: Node | null = domNode.parentNode;\n if (!parentNode) {\n throw new Error(\"The provided domNode does not have a parentNode.\");\n }\n\n const observer = new MutationObserver((mutationsList) => {\n for (const mutation of mutationsList) {\n if (mutation.removedNodes.length > 0) {\n for (const removedNode of mutation.removedNodes) {\n if (removedNode === domNode) {\n // Defer check: if node is re-inserted (move), it will be connected\n queueMicrotask(() => {\n if (!domNode.isConnected) {\n // Node was actually unmounted\n onUnmount();\n observer.disconnect();\n return;\n }\n\n // Node was moved, not unmounted: re-arm observer on new parent\n const newParent = domNode.parentNode;\n if (newParent && newParent !== parentNode) {\n parentNode = newParent;\n observer.disconnect();\n observer.observe(parentNode, { childList: true });\n }\n });\n return;\n }\n }\n }\n }\n });\n\n // Observe the parentNode for child removals\n observer.observe(parentNode, { childList: true });\n};\n\n/** lifecycle event attachment has been implemented separately, because it is also required to run when partially updating the DOM */\nexport const handleLifecycleEventsForOnMount = (newEl: HTMLElement) => {\n // check for a lifecycle \"onMount\" hook and call it\n if (typeof (newEl as any)?.$onMount === \"function\") {\n (newEl as any).$onMount!(newEl); // remove the hook after it's been called\n (newEl as any).$onMount = null;\n }\n\n // optionally check for a element lifecycle \"onUnmount\" and hook it up\n if (typeof (newEl as any)?.$onUnmount === \"function\") {\n // register the unmount observer (MutationObserver)\n observeUnmount(newEl as HTMLElement, (newEl as any).$onUnmount!);\n }\n};\n\nexport const getRenderer = (document: Document): DomAbstractionImpl => {\n // DOM abstraction layer for manipulation\n const renderer = {\n hasElNamespace: (domElement: Element | Document): boolean =>\n (domElement as Element).namespaceURI === nsMap.svg,\n\n hasSvgNamespace: (\n parentElement: Element | Document,\n type: string,\n ): boolean =>\n renderer.hasElNamespace(parentElement) &&\n type !== \"STYLE\" &&\n type !== \"SCRIPT\",\n\n createElementOrElements: (\n virtualNode: RenderInput,\n parentDomElement?: Element | Document,\n ): Array<Element | Text | undefined> | Element | Text | undefined => {\n if (Array.isArray(virtualNode)) {\n return renderer.createChildElements(virtualNode, parentDomElement);\n }\n if (typeof virtualNode !== \"undefined\") {\n return renderer.createElement(virtualNode, parentDomElement);\n }\n // undefined virtualNode -> e.g. when a tsx variable is used in markup which is undefined\n return renderer.createTextNode(\"\", parentDomElement);\n },\n\n createElement: (\n virtualNode: RenderInput,\n parentDomElement?: Element | Document,\n ): Element | undefined => {\n let newEl: Element | undefined;\n\n // VERIFIED: comment nodes are leaves in the DOM (no attributes or\n // children), so none of the element setup below applies\n if (isCommentVNode(virtualNode)) {\n const comment = document.createComment(virtualNode.value ?? \"\");\n parentDomElement?.appendChild(comment);\n return comment as unknown as Element;\n }\n\n try {\n // if a synchronous function is still a function, VDOM has obviously not resolved, probably an\n // Error occurred while generating the VDOM (in JSX runtime)\n if (\n typeof virtualNode === \"function\" &&\n virtualNode.constructor.name === \"AsyncFunction\"\n ) {\n newEl = document.createElement(\"div\");\n } else if (\n typeof virtualNode === \"object\" &&\n virtualNode !== null &&\n \"type\" in virtualNode\n ) {\n const vNode = virtualNode as VNode;\n\n if (typeof vNode.type === \"function\") {\n newEl = document.createElement(\"div\");\n (newEl as HTMLElement).innerText =\n `FATAL ERROR: ${(vNode.type as { _error?: string })._error}`;\n } else if (\n // SVG support\n (typeof vNode.type === \"string\" &&\n vNode.type.toUpperCase() === \"SVG\") ||\n (parentDomElement &&\n renderer.hasSvgNamespace(\n parentDomElement,\n typeof vNode.type === \"string\" ? vNode.type.toUpperCase() : \"\",\n ))\n ) {\n // SVG support\n newEl = document.createElementNS(nsMap.svg, vNode.type as string);\n } else {\n newEl = document.createElement(vNode.type as string);\n }\n\n if (vNode.attributes) {\n renderer.setAttributes(vNode, newEl as Element);\n\n // apply dangerouslySetInnerHTML if provided\n if (vNode.attributes.dangerouslySetInnerHTML) {\n (newEl as HTMLElement).innerHTML =\n vNode.attributes.dangerouslySetInnerHTML.__html;\n }\n }\n\n // Skip child creation when dangerouslySetInnerHTML is used (matches React semantics)\n if (vNode.children && !vNode.attributes?.dangerouslySetInnerHTML) {\n renderer.createChildElements(vNode.children, newEl as Element);\n }\n } else {\n // Fallback for unexpected types (primitives should be handled by createTextNode, but just in case)\n // If virtualNode is a primitive at this point, original logic would try to use it as tag name or crash.\n // We'll create a text node wrapped in span or similar?\n // Attempting to match original implementation which forced Cast.\n // If 'type' is missing, it's not a valid VNode.\n // Original was: newEl = document.createElement(virtualNode.type as string);\n // If it's a string, type is undefined. document.createElement(\"undefined\") -> <undefined> element.\n if (\n typeof virtualNode === \"string\" ||\n typeof virtualNode === \"number\"\n ) {\n // Creating an element with the value as tag name seems wrong but that's what the old code did if it got here.\n // However, createElementOrElements dispatches strings to createTextNode.\n // So we might be safe here.\n newEl = document.createElement(String(virtualNode));\n }\n }\n\n if (newEl && parentDomElement) {\n parentDomElement.appendChild(newEl);\n handleLifecycleEventsForOnMount(newEl as HTMLElement);\n }\n } catch (e) {\n console.error(\n \"Fatal error! Error happend while rendering the VDOM!\",\n e,\n virtualNode,\n );\n throw e;\n }\n return newEl as Element;\n },\n\n createTextNode: (text: string, domElement?: Element | Document): Text => {\n const node = document.createTextNode(text.toString());\n\n if (domElement) {\n domElement.appendChild(node);\n }\n return node;\n },\n\n createChildElements: (\n virtualChildren: VNodeChildren,\n domElement?: Element | Document,\n ): Array<Element | Text | undefined> => {\n const children: Array<Element | Text | undefined> = [];\n\n for (let i = 0; i < virtualChildren.length; i++) {\n const virtualChild = virtualChildren[i];\n\n // Skip booleans entirely - {true} and {false} render nothing (React/JSX semantics)\n if (typeof virtualChild === \"boolean\") {\n continue;\n }\n\n if (\n virtualChild === null ||\n (typeof virtualChild !== \"object\" &&\n typeof virtualChild !== \"function\")\n ) {\n children.push(\n renderer.createTextNode(\n (typeof virtualChild === \"undefined\" || virtualChild === null\n ? \"\"\n : virtualChild!\n ).toString(),\n domElement,\n ),\n );\n } else {\n children.push(\n renderer.createElement(virtualChild as VNode, domElement),\n );\n }\n }\n return children;\n },\n\n setAttribute: (name: string, value: any, domElement: Element) => {\n // attributes not set (undefined) are ignored; use null value to reset an attributes state\n if (typeof value === \"undefined\") return;\n\n if (name === DANGEROUSLY_SET_INNER_HTML_ATTRIBUTE) return;\n\n // internal list key: store on element, do not serialize into DOM\n if (name === \"key\") {\n (domElement as HTMLElement & { _defussKey?: string })._defussKey =\n String(value);\n return;\n }\n\n // save ref as { current: DOMElement } in ref object\n if (name === REF_ATTRIBUTE_NAME && typeof value !== \"function\") {\n const ref = value as { current?: unknown; orphan?: boolean };\n ref.current = domElement;\n (domElement as any)._defussRef = value;\n\n (domElement as any).$onUnmount = queueCallback(() => {\n // value.orphan = true;\n });\n\n if (domElement.parentNode) {\n observeUnmount(domElement, (domElement as any).$onUnmount);\n } else {\n queueMicrotask(() => {\n if (domElement.parentNode) {\n observeUnmount(domElement, (domElement as any).$onUnmount);\n }\n });\n }\n return;\n }\n\n // event props: delegate globally; still keep defuss lifecycle hooks\n const parsed = parseEventPropName(name);\n if (parsed && typeof value === \"function\") {\n const { eventType, capture } = parsed;\n\n if (eventType === \"mount\") {\n (domElement as any).$onMount = queueCallback(value as () => void);\n return;\n }\n\n if (eventType === \"unmount\") {\n if ((domElement as any).$onUnmount) {\n const existingUnmount = (domElement as any)\n .$onUnmount as () => void;\n (domElement as any).$onUnmount = () => {\n existingUnmount();\n (value as () => void)();\n };\n } else {\n (domElement as any).$onUnmount = queueCallback(value as () => void);\n }\n return;\n }\n\n registerDelegatedEvent(\n domElement as HTMLElement,\n eventType,\n value as EventListener,\n { capture },\n );\n return;\n }\n\n // transforms className=\"...\" -> class=\"...\"\n if (name === \"className\") {\n name = CLASS_ATTRIBUTE_NAME;\n }\n\n // transforms class={['a', 'b']} into class=\"a b\"\n if (name === CLASS_ATTRIBUTE_NAME && Array.isArray(value)) {\n value = value.filter((val) => !!val).join(\" \");\n }\n\n // SVG support\n const nsEndIndex = name.match(/[A-Z]/)?.index;\n if (renderer.hasElNamespace(domElement) && nsEndIndex) {\n const ns = name.substring(0, nsEndIndex).toLowerCase();\n const attrName = name.substring(nsEndIndex, name.length).toLowerCase();\n const namespace = nsMap[ns as keyof typeof nsMap] || null;\n domElement.setAttributeNS(\n namespace,\n ns === XLINK_ATTRIBUTE_NAME || ns === XMLNS_ATTRIBUTE_NAME\n ? `${ns}:${attrName}`\n : name,\n String(value),\n );\n } else if (name === \"style\" && typeof value !== \"string\") {\n const styleObj = value as Record<string, string | number>;\n for (const prop of Object.keys(styleObj)) {\n (domElement as HTMLElement).style[prop as any] = String(\n styleObj[prop],\n );\n }\n } else if (typeof value === \"boolean\") {\n (domElement as any)[name] = value;\n // Also set/remove the attribute so SSG serialization includes it\n if (value) {\n domElement.setAttribute(name, \"\");\n } else {\n domElement.removeAttribute(name);\n }\n } else if (\n // Controlled input props: use property assignment for live value,\n // AND setAttribute so SSG serialization (w3c-xmlserializer) includes it\n (name === \"value\" || name === \"checked\" || name === \"selectedIndex\") &&\n (domElement.nodeName === \"INPUT\" ||\n domElement.nodeName === \"TEXTAREA\" ||\n domElement.nodeName === \"SELECT\")\n ) {\n (domElement as any)[name] = value;\n if (name === \"checked\") {\n if (value) {\n domElement.setAttribute(\"checked\", \"\");\n } else {\n domElement.removeAttribute(\"checked\");\n }\n } else if (name === \"value\") {\n domElement.setAttribute(\"value\", String(value));\n }\n // selectedIndex has no HTML attribute equivalent - skip setAttribute\n } else {\n domElement.setAttribute(name, String(value));\n }\n },\n\n setAttributes: (\n virtualNode: VNode<VNodeAttributes>,\n domElement: Element,\n ) => {\n // attributes are optional on hand-written VNodes — guard instead of the\n // `!` assertion, which crashed patching an element with an\n // attributes-less vnode (Object.keys(undefined) throws)\n const attrNames = Object.keys(virtualNode.attributes ?? {});\n for (let i = 0; i < attrNames.length; i++) {\n renderer.setAttribute(\n attrNames[i],\n virtualNode.attributes![attrNames[i]],\n domElement,\n );\n }\n },\n };\n return renderer;\n};\n",
|
|
9
|
-
"import type {\n Globals,\n RenderInput,\n VNode,\n VNodeAttributes,\n VNodeChild,\n} from \"./types.js\";\nimport {\n getRenderer,\n handleLifecycleEventsForOnMount,\n} from \"./renderer.js\";\nimport { isCommentVNode } from \"./html.js\";\nimport {\n clearDelegatedEventsDeep,\n getRegisteredEventKeys,\n parseEventPropName,\n removeDelegatedEventByKey,\n} from \"./delegated-events.js\";\nimport { FROM_DOM_MARKER } from \"./html.js\";\n\n/**\n * Compares two DOM nodes for equality with performance optimizations.\n * 1. Checks for reference equality.\n * 2. Compares node types.\n * 3. For Element nodes, compares tag names and attributes.\n * 4. For Text and Comment nodes, compares their data.\n */\nexport const areDomNodesEqual = (oldNode: Node, newNode: Node): boolean => {\n // return true if both references are identical\n if (oldNode === newNode) return true;\n\n // compare node types\n if (oldNode.nodeType !== newNode.nodeType) return false;\n\n // handle Element nodes\n if (oldNode.nodeType === 1 /* Node.ELEMENT_NODE */) {\n const oldElement = oldNode as Element;\n const newElement = newNode as Element;\n\n // compare tag names\n if (oldElement.tagName !== newElement.tagName) return false;\n\n const oldAttrs = oldElement.attributes;\n const newAttrs = newElement.attributes;\n\n // compare number of attributes\n if (oldAttrs.length !== newAttrs.length) return false;\n\n // iterate and compare each attribute's name and value\n for (let i = 0; i < oldAttrs.length; i++) {\n const oldAttr = oldAttrs[i];\n const newAttrValue = newElement.getAttribute(oldAttr.name);\n if (oldAttr.value !== newAttrValue) return false;\n }\n }\n\n // handle Text and Comment nodes\n if (\n oldNode.nodeType === 3 /* Node.TEXT_NODE */ ||\n oldNode.nodeType === 8 /* Node.COMMENT_NODE */\n ) {\n if (oldNode.nodeValue !== newNode.nodeValue) return false;\n }\n return true;\n};\n\n/********************************************************\n * 1) Define a \"valid\" child type & utilities\n ********************************************************/\nexport type ValidChild =\n | string\n | number\n | boolean\n | null\n | undefined\n | VNode<VNodeAttributes>;\n\n/**\n * How top-level children are reconciled:\n * - `\"replace\"` (default): full reconciliation — unmentioned nodes are removed.\n * - `\"diff\"`: partial updates — only patch items addressed by `key`/`id` are\n * applied (attributes merge, new items append, unmentioned nodes untouched).\n */\nexport type MorphMode = \"replace\" | \"diff\";\n\nfunction isTextLike(value: unknown): value is string | number | boolean {\n return (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n );\n}\n\nfunction isVNode(value: unknown): value is VNode<VNodeAttributes> {\n return Boolean(\n value &&\n typeof value === \"object\" &&\n \"type\" in (value as Record<string, unknown>),\n );\n}\n\nfunction toValidChild(\n child: VNodeChild,\n // diff mode: a partial patch item may omit `type` (borrowed from the node\n // it addresses) — `{ attributes: ... }` alone is a valid patch object there\n lenient = false,\n): ValidChild | undefined {\n if (child == null) return child; // null or undefined\n if (isTextLike(child)) return child;\n\n if (isVNode(child)) return child;\n\n if (\n lenient &&\n child &&\n typeof child === \"object\" &&\n \"attributes\" in (child as Record<string, unknown>)\n )\n return child as unknown as ValidChild;\n\n // e.g. function or {} -> filter out\n return undefined;\n}\n\n/** fuse consecutive text-like nodes to preserve DOM stability (matches hydrate's behavior) */\nfunction normalizeChildren(\n input: RenderInput,\n lenient = false,\n): Array<ValidChild> {\n const raw: Array<ValidChild> = [];\n\n const pushChild = (child: unknown) => {\n if (Array.isArray(child)) {\n child.forEach(pushChild);\n return;\n }\n\n const valid = toValidChild(child as VNodeChild, lenient);\n if (typeof valid === \"undefined\") return;\n\n // unwrap Fragment-ish nodes (defuss sometimes uses \"fragment\", some code uses \"Fragment\")\n if (\n isVNode(valid) &&\n (valid.type === \"fragment\" || valid.type === \"Fragment\")\n ) {\n const nested = Array.isArray(valid.children) ? valid.children : [];\n nested.forEach(pushChild);\n return;\n }\n\n // ignore booleans/null/undefined as render-nothing\n if (\n valid === null ||\n typeof valid === \"undefined\" ||\n typeof valid === \"boolean\"\n )\n return;\n\n raw.push(valid);\n };\n\n pushChild(input);\n\n // fuse consecutive text nodes into a single string\n const fused: Array<ValidChild> = [];\n let buffer: string | null = null;\n\n const flush = () => {\n if (buffer !== null && buffer.length > 0) fused.push(buffer);\n buffer = null;\n };\n\n for (const child of raw) {\n if (\n typeof child === \"string\" ||\n typeof child === \"number\" ||\n typeof child === \"boolean\"\n ) {\n buffer = (buffer ?? \"\") + String(child);\n continue;\n }\n\n flush();\n fused.push(child);\n }\n\n flush();\n return fused;\n}\n\nfunction getVNodeMatchKey(child: ValidChild): string | null {\n if (!child || typeof child !== \"object\") return null;\n\n const key = child.attributes?.key;\n if (typeof key === \"string\" || typeof key === \"number\")\n return `k:${String(key)}`;\n\n const id = child.attributes?.id;\n if (typeof id === \"string\" && id.length > 0) return `id:${id}`;\n\n return null;\n}\n\n/** human-readable item description for diff-mode error messages */\nfunction describePatchItem(child: ValidChild): string {\n if (child && typeof child === \"object\") {\n return `<${typeof child.type === \"string\" ? child.type : \"component\"}>`;\n }\n return \"plain text\";\n}\n\nfunction getDomMatchKeys(node: Node): Array<string> {\n if (node.nodeType !== 1 /* Node.ELEMENT_NODE */) return [];\n\n const el = node as HTMLElement;\n const keys: Array<string> = [];\n\n // prefer internal key storage, but also accept legacy `key` attribute if present\n const internalKey = (el as HTMLElement & { _defussKey?: string })._defussKey;\n if (internalKey) keys.push(`k:${internalKey}`);\n\n const attrKey = el.getAttribute(\"key\");\n if (attrKey) keys.push(`k:${attrKey}`);\n\n const id = el.id;\n if (id) keys.push(`id:${id}`);\n\n return keys;\n}\n\n/********************************************************\n * 2) Check if a DOM node and a ValidChild match by type\n ********************************************************/\nfunction areNodeAndChildMatching(domNode: Node, child: ValidChild): boolean {\n if (\n typeof child === \"string\" ||\n typeof child === \"number\" ||\n typeof child === \"boolean\"\n ) {\n return domNode.nodeType === 3 /* Node.TEXT_NODE */;\n }\n\n if (isCommentVNode(child)) return domNode.nodeType === 8 /* Node.COMMENT_NODE */;\n\n if (child && typeof child === \"object\") {\n if (domNode.nodeType !== 1 /* Node.ELEMENT_NODE */) return false;\n\n const el = domNode as HTMLElement;\n const oldTag = el.tagName.toLowerCase();\n const newTag =\n typeof child.type === \"string\" ? child.type.toLowerCase() : \"\";\n if (!newTag || oldTag !== newTag) return false;\n\n // Match only by tag name - class changes should be handled by patchElementInPlace\n // This prevents node churn when classes are toggled (e.g., \"danger\" on selection)\n return true;\n }\n\n return false;\n}\n\n/********************************************************\n * 3) Create brand new DOM node(s) from a ValidChild\n ********************************************************/\nfunction createDomFromChild(\n child: ValidChild,\n globals: Globals,\n): Array<Node> | undefined {\n const renderer = getRenderer(globals.window.document);\n\n if (child == null) return undefined;\n\n if (\n typeof child === \"string\" ||\n typeof child === \"number\" ||\n typeof child === \"boolean\"\n ) {\n return [globals.window.document.createTextNode(String(child))];\n }\n\n // create without parent (we'll insert manually and run lifecycle hooks afterwards)\n const created = renderer.createElementOrElements(child) as\n | Node\n | Array<Node>\n | undefined;\n\n if (!created) return undefined;\n const nodes = Array.isArray(created) ? created : [created];\n return nodes.filter(Boolean) as Array<Node>;\n}\n\n/********************************************************\n * 4) Patch an element node in place (attributes + children)\n ********************************************************/\nfunction shouldPreserveFormStateAttribute(\n el: Element,\n attrName: string,\n vnode: VNode<VNodeAttributes>,\n): boolean {\n const tag = el.tagName.toLowerCase();\n const hasExplicit = Object.hasOwn(vnode.attributes ?? {}, attrName);\n\n if (hasExplicit) return false;\n\n // preserve uncontrolled input/textarea/select state unless explicitly controlled by VDOM\n if (tag === \"input\") return attrName === \"value\" || attrName === \"checked\";\n if (tag === \"textarea\") return attrName === \"value\";\n if (tag === \"select\") return attrName === \"value\";\n return false;\n}\n\nfunction patchElementInPlace(\n el: Element,\n vnode: VNode<VNodeAttributes>,\n globals: Globals,\n // diff mode: the vnode is a partial patch — undeclared attributes and\n // delegated handlers are \"not mentioned\", never \"unset\", so removal is skipped\n mergeAttributes = false,\n): void {\n const renderer = getRenderer(globals.window.document);\n\n // remove old attributes not present (but preserve uncontrolled form state)\n const existingAttrs = mergeAttributes ? [] : Array.from(el.attributes);\n const nextAttrs = vnode.attributes ?? {};\n\n for (const attr of existingAttrs) {\n const { name } = attr;\n\n // do not remove internal key if it ever existed as attribute\n if (name === \"key\") continue;\n\n // do not remove event-ish attributes; handlers are delegated elsewhere\n if (name.startsWith(\"on\")) continue;\n\n // treat class/className as equivalent\n if (\n name === \"class\" &&\n (Object.hasOwn(nextAttrs, \"class\") ||\n Object.hasOwn(nextAttrs, \"className\"))\n ) {\n continue;\n }\n\n if (!Object.hasOwn(nextAttrs, name)) {\n if (shouldPreserveFormStateAttribute(el, name, vnode)) continue;\n el.removeAttribute(name);\n }\n }\n\n // Remove stale event handlers: compute registered phase keys - next vnode phase keys\n // This is phase-aware: onClick + onClickCapture → onClickCapture only will correctly\n // remove the bubble handler while keeping the capture handler.\n // Skipped for DOM-derived vnodes (HTML strings / DOM nodes): those cannot declare\n // handlers, so existing delegated handlers are preserved like uncontrolled form state.\n const preserveDelegatedHandlers =\n mergeAttributes ||\n Boolean((nextAttrs as Record<PropertyKey, unknown>)[FROM_DOM_MARKER]);\n\n if (!preserveDelegatedHandlers) {\n const registeredKeys = getRegisteredEventKeys(el as HTMLElement);\n const nextEventKeys = new Set<string>();\n for (const propName of Object.keys(nextAttrs)) {\n const parsed = parseEventPropName(propName);\n if (parsed) {\n const phase = parsed.capture ? \"capture\" : \"bubble\";\n nextEventKeys.add(`${parsed.eventType}:${phase}`);\n }\n }\n for (const key of registeredKeys) {\n if (!nextEventKeys.has(key)) {\n const [eventType, phase] = key.split(\":\");\n removeDelegatedEventByKey(\n el as HTMLElement,\n eventType,\n phase as \"bubble\" | \"capture\",\n );\n }\n }\n }\n\n // set new attributes (includes ref + delegated events via renderer.setAttribute)\n renderer.setAttributes(vnode, el);\n\n // Trigger onMount lifecycle for morphed elements that have a new onMount callback\n // This ensures onMount fires on route changes even when elements are morphed in place\n handleLifecycleEventsForOnMount(el as HTMLElement);\n\n // dangerouslySetInnerHTML => skip child reconciliation\n const d = vnode.attributes?.dangerouslySetInnerHTML;\n if (d && typeof d === \"object\" && typeof d.__html === \"string\") {\n el.innerHTML = d.__html;\n return;\n }\n\n const tag = el.tagName.toLowerCase();\n\n // preserve textarea live value unless explicitly controlled\n if (tag === \"textarea\") {\n const isControlled = Object.hasOwn(nextAttrs, \"value\");\n const isActive = el.ownerDocument?.activeElement === el;\n if (isActive && !isControlled) return;\n }\n\n // diff mode: children are \"not mentioned\" unless explicitly declared, so an\n // attributes-only patch item must not clear the node's existing children.\n // HTML-derived vnodes always carry a (possibly empty) children array —\n // empty means \"undeclared\" there, exactly like absent form attributes.\n // VNode/JSX input keeps the distinction: children: [] clears explicitly.\n if (\n mergeAttributes &&\n (vnode.children === undefined ||\n (vnode.children.length === 0 &&\n (nextAttrs as Record<PropertyKey, unknown>)[FROM_DOM_MARKER]))\n )\n return;\n\n // reconcile children (direct call - bypasses morph guard for internal recursion)\n morphDomDirect(el, (vnode.children ?? []) as RenderInput, globals);\n}\n\n/********************************************************\n * 5) Morph a single DOM node to match a ValidChild\n ********************************************************/\n\n/**\n * Swap `next` in for `old`, clearing the old subtree's handlers first — the\n * same teardown as removal, so delegated handlers and facade listeners\n * (onClearDelegatedEvents hooks) never outlive a replaced element.\n * VERIFIED: a keyed tag change tears down on() listeners (suite.browser.test.ts)\n */\nfunction replaceNode(old: Node, next: Node): void {\n if (old.nodeType === 1 /* Node.ELEMENT_NODE */)\n clearDelegatedEventsDeep(old as HTMLElement);\n old.parentNode?.replaceChild(next, old);\n}\nfunction morphNode(\n domNode: Node,\n child: ValidChild,\n globals: Globals,\n mergeAttributes = false,\n): Node | null {\n // text-like\n if (\n typeof child === \"string\" ||\n typeof child === \"number\" ||\n typeof child === \"boolean\"\n ) {\n const text = String(child);\n\n if (domNode.nodeType === 3 /* Node.TEXT_NODE */) {\n if (domNode.nodeValue !== text) domNode.nodeValue = text;\n return domNode;\n }\n\n const next = globals.window.document.createTextNode(text);\n replaceNode(domNode, next);\n return next;\n }\n\n // comment: patch data in place, like text\n if (isCommentVNode(child)) {\n const data = child.value ?? \"\";\n\n if (domNode.nodeType === 8 /* Node.COMMENT_NODE */) {\n if (domNode.nodeValue !== data) domNode.nodeValue = data;\n return domNode;\n }\n\n const next = globals.window.document.createComment(data);\n replaceNode(domNode, next);\n return next;\n }\n\n // element-like (VNode)\n if (child && typeof child === \"object\") {\n const newType = typeof child.type === \"string\" ? child.type : null;\n if (!newType) return domNode;\n\n if (domNode.nodeType !== 1 /* Node.ELEMENT_NODE */) {\n const created = createDomFromChild(child, globals);\n const first = Array.isArray(created) ? created[0] : created;\n if (!first) return null;\n\n domNode.parentNode?.replaceChild(first, domNode);\n handleLifecycleEventsForOnMount(first as HTMLElement);\n return first;\n }\n\n const el = domNode as Element;\n const oldTag = el.tagName.toLowerCase();\n const newTag = newType.toLowerCase();\n\n if (oldTag !== newTag) {\n const created = createDomFromChild(child, globals);\n const first = Array.isArray(created) ? created[0] : created;\n if (!first) return null;\n\n replaceNode(el, first);\n handleLifecycleEventsForOnMount(first as HTMLElement);\n return first;\n }\n\n patchElementInPlace(el, child as VNode<VNodeAttributes>, globals, mergeAttributes);\n return el;\n }\n\n // null/undefined => remove\n if (domNode.nodeType === 1 /* Node.ELEMENT_NODE */)\n clearDelegatedEventsDeep(domNode as HTMLElement);\n domNode.parentNode?.removeChild(domNode);\n return null;\n}\n\n/********************************************************\n * 6) Morph guard - tags DOM subtrees as \"rendering\" to prevent\n * re-entrant / conflicting morphs on the same or ancestor nodes.\n * Unrelated subtrees morph in parallel without blocking.\n ********************************************************/\nconst renderingNodes = new WeakSet<Element>();\nconst pendingMorphs = new Map<\n Element,\n { vdom: RenderInput; globals: Globals; mode: MorphMode }\n>();\n\n/**\n * Resolve the render globals from an element's own document when not given\n * explicitly (isomorphic: browser window, happy-dom window, multi-document).\n */\nexport const resolveGlobals = (el?: Element, globals?: Globals): Globals => {\n if (globals) return globals;\n const win = (el?.ownerDocument?.defaultView ??\n globalThis) as unknown as Globals;\n return { window: win } as unknown as Globals;\n};\n\nfunction isAncestorRendering(el: Element): boolean {\n let current = el.parentElement;\n while (current) {\n if (renderingNodes.has(current)) return true;\n current = current.parentElement;\n }\n return false;\n}\n\nfunction flushPendingMorphs(): void {\n if (pendingMorphs.size === 0) return;\n\n // Snapshot and clear to avoid infinite loops if flush triggers more morphs\n const snapshot = [...pendingMorphs.entries()];\n pendingMorphs.clear();\n\n for (const [el, { vdom, globals, mode }] of snapshot) {\n // Skip if element was detached during parent morph\n if (!el.isConnected) continue;\n // Re-enter through guarded path (handles nested conflicts)\n updateDomWithVdom(el, vdom, globals, mode);\n }\n}\n\n/**\n * Guarded entry point for DOM morphing.\n *\n * If the target element (or an ancestor) is already being morphed,\n * the render is queued (latest-wins) and replayed after the active\n * morph finishes. Morphs on unrelated subtrees proceed immediately\n * without blocking - conflict-free parallel rendering.\n *\n * `globals` is optional: it is derived from `parentElement.ownerDocument`\n * when omitted.\n *\n * `mode` defaults to `\"replace\"` (full reconciliation). Pass `\"diff\"` for\n * partial updates: only `key`/`id`-addressed patch items are applied\n * (attributes merged, new keyed items appended, unmentioned nodes untouched).\n */\nexport function updateDomWithVdom(\n parentElement: Element,\n newVDOM: RenderInput,\n globals?: Globals,\n mode: MorphMode = \"replace\",\n): void {\n const resolvedGlobals = resolveGlobals(parentElement, globals);\n\n // Re-entrant or ancestor conflict → queue latest, return\n if (renderingNodes.has(parentElement) || isAncestorRendering(parentElement)) {\n pendingMorphs.set(parentElement, {\n vdom: newVDOM,\n globals: resolvedGlobals,\n mode,\n });\n return;\n }\n\n renderingNodes.add(parentElement);\n try {\n morphDomDirect(parentElement, newVDOM, resolvedGlobals, mode);\n } finally {\n renderingNodes.delete(parentElement);\n }\n\n // Flush any morphs that were queued during this render\n flushPendingMorphs();\n}\n\n/********************************************************\n * 6b) Diff mode — partial change-sets (patch + append only)\n ********************************************************/\n/**\n * Apply a partial change-set to `targetRoot`: every top-level item must be an\n * element addressed by `key` (preferred) or `id`. Matched nodes are patched in\n * place with attributes *merged* (undeclared attributes, delegated handlers\n * and children stay untouched); unmatched items are appended as new nodes.\n * Nothing else changes: unmentioned siblings keep identity, order and state —\n * diff mode never removes and never moves, so addressing is unambiguous.\n *\n * Why: stream/AI-driven partial updates without resending the whole subtree.\n * Tag changes on an addressed node are applied as an honest in-place\n * replacement (the item fully declares that node).\n */\nfunction morphDiff(\n targetRoot: ParentNode & Node,\n patchItems: Array<ValidChild>,\n globals: Globals,\n): void {\n // first-wins keyed pool of the current children — diff never removes, so\n // duplicate keys can simply share the first node as the address owner\n const keyedPool = new Map<string, Node>();\n for (const node of Array.from(targetRoot.childNodes)) {\n for (const k of getDomMatchKeys(node)) {\n if (!keyedPool.has(k)) keyedPool.set(k, node);\n }\n }\n\n for (const item of patchItems) {\n // formatting whitespace between change-set items (e.g. newlines + indent\n // in a template literal) parses to text nodes but carries no meaning —\n // skip it; only *meaningful* plain text is unaddressable and throws\n if (typeof item === \"string\" && item.trim() === \"\") continue;\n\n // top-level comments in a change-set are annotations with no address:\n // diff never removes or moves, and appending would duplicate them on\n // every repeated patch — skip them (comments *inside* items do morph).\n // VERIFIED: a repeated commented patch leaves no duplicates (morph-comments.test.ts)\n if (isCommentVNode(item)) continue;\n\n // booleans/null are already filtered by normalizeChildren; anything\n // without a key/id (incl. plain text) cannot be addressed unambiguously\n const key = getVNodeMatchKey(item);\n\n if (!key) {\n throw new Error(\n `morph diff: patch items must be elements with a key or id attribute (got ${describePatchItem(item)})`,\n );\n }\n\n const match = keyedPool.get(key);\n\n if (match) {\n // Tag-less patch items are pure patches: borrow the addressed node's\n // tag (only *new* items need one — to create it). An explicitly\n // different tag still replaces the node.\n const patchItem =\n item && typeof item === \"object\" && !(item as VNode).type\n ? { ...item, type: (match as Element).tagName.toLowerCase() }\n : item;\n\n // same tag -> attribute merge (+ declared children); tag change ->\n // in-place replacement by morphNode; mergeAttributes keeps the diff\n // contract (no attribute/handler removal) either way\n morphNode(match, patchItem, globals, true);\n continue;\n }\n\n if (!(item as VNode)?.type) {\n throw new Error(\n `morph diff: new (unmatched) patch items must declare a tag (type), got key/id \"${key}\"`,\n );\n }\n\n // new keyed item -> append (never inserted \"in order\" implicitly: moving\n // or positioning unmentioned siblings would be a guess)\n const created = createDomFromChild(item, globals) ?? [];\n for (const node of created) {\n targetRoot.appendChild(node);\n handleLifecycleEventsForOnMount(node as HTMLElement);\n }\n }\n}\n\n/********************************************************\n * 7) Raw morph implementation (key/id aware, move-not-replace)\n * Called directly by the guard and by internal recursive\n * child reconciliation (patchElementInPlace).\n ********************************************************/\nfunction morphDomDirect(\n parentElement: Element,\n newVDOM: RenderInput,\n globals: Globals,\n mode: MorphMode = \"replace\",\n): void {\n // Custom elements (hyphenated tags) use light DOM for slotted content.\n // Other elements with shadowRoot should target the shadow root.\n const el = parentElement as HTMLElement;\n const isCustomElement = el.tagName.includes(\"-\");\n const targetRoot: ParentNode & Node =\n el.shadowRoot && !isCustomElement ? el.shadowRoot : parentElement;\n\n const nextChildren = normalizeChildren(newVDOM, mode === \"diff\");\n\n if (mode === \"diff\") {\n morphDiff(targetRoot, nextChildren, globals);\n return;\n }\n\n // snapshot existing children once for matching pools\n const existing = Array.from(targetRoot.childNodes);\n\n const keyedPool = new Map<string, Node>();\n const nodeKeys = new WeakMap<Node, Array<string>>();\n const unkeyedPool: Array<Node> = [];\n\n for (const node of existing) {\n const keys = getDomMatchKeys(node);\n if (keys.length > 0) {\n nodeKeys.set(node, keys);\n let addedToKeyedPool = false;\n for (const k of keys) {\n if (!keyedPool.has(k)) {\n keyedPool.set(k, node);\n addedToKeyedPool = true;\n }\n }\n // all keys duplicates of already-pooled nodes: fall back to the\n // unkeyed pool so the node can still be matched — and, crucially,\n // is removed when left over (duplicate keys must not leak nodes)\n if (!addedToKeyedPool) {\n unkeyedPool.push(node);\n }\n } else {\n unkeyedPool.push(node);\n }\n }\n\n const consumeKeyedNode = (node: Node) => {\n const keys = nodeKeys.get(node) ?? [];\n for (const k of keys) keyedPool.delete(k);\n };\n\n const takeUnkeyedMatch = (child: ValidChild): Node | undefined => {\n // try to find a compatible node (preserves focus/state by moving instead of replacing)\n for (let i = 0; i < unkeyedPool.length; i++) {\n const candidate = unkeyedPool[i];\n if (areNodeAndChildMatching(candidate, child)) {\n unkeyedPool.splice(i, 1);\n return candidate;\n }\n }\n\n // SAFE: no match => don't reuse something random, create new node instead\n return undefined;\n };\n\n let domIndex = 0;\n\n for (const child of nextChildren) {\n const key = getVNodeMatchKey(child);\n\n let match: Node | undefined;\n\n if (key) {\n match = keyedPool.get(key);\n if (match) consumeKeyedNode(match);\n } else {\n match = takeUnkeyedMatch(child);\n }\n\n const anchor = targetRoot.childNodes[domIndex] ?? null;\n\n if (match) {\n // move node into place (preserves identity/state)\n if (match !== anchor) {\n targetRoot.insertBefore(match, anchor);\n }\n\n const morphed = morphNode(match, child, globals);\n\n // if morphNode replaced it, ensure we still have the correct node at domIndex\n if (morphed && morphed !== match) {\n // replacement already occurred in-place, nothing else to do\n }\n\n domIndex++;\n continue;\n }\n\n // no match => create and insert\n const created = createDomFromChild(child, globals);\n if (!created || (Array.isArray(created) && created.length === 0)) continue;\n\n const nodes = Array.isArray(created) ? created : [created];\n for (const node of nodes) {\n targetRoot.insertBefore(node, anchor);\n handleLifecycleEventsForOnMount(node as HTMLElement);\n domIndex++;\n }\n }\n\n // remove remaining unmatched nodes (both keyed leftovers and unkeyed leftovers)\n const remaining = new Set<Node>();\n\n for (const node of unkeyedPool) remaining.add(node);\n for (const node of keyedPool.values()) remaining.add(node);\n\n for (const node of remaining) {\n if (node.parentNode === targetRoot) {\n // Clear delegated events before removal to prevent handler leaks\n // (realm-safe element check: works across windows / SSR DOM implementations)\n if (node.nodeType === 1 /* Node.ELEMENT_NODE */) {\n clearDelegatedEventsDeep(node as HTMLElement);\n }\n targetRoot.removeChild(node);\n }\n }\n}\n\n/**\n * Directly blow away all children in `parentElement` and create new DOM\n * from `newVDOM`. This never skips or leaves behind stale nodes,\n * at the cost of losing partial update performance.\n *\n * `globals` is optional: it is derived from `parentElement.ownerDocument`\n * when omitted.\n */\nexport function replaceDomWithVdom(\n parentElement: Element,\n newVDOM: RenderInput,\n globals?: Globals,\n) {\n const resolvedGlobals = resolveGlobals(parentElement, globals);\n\n // 1) Clear all existing DOM children\n while (parentElement.firstChild) {\n parentElement.removeChild(parentElement.firstChild);\n }\n\n // 2) Re-render from scratch\n const renderer = getRenderer(resolvedGlobals.window.document);\n\n const newDom = renderer.createElementOrElements(\n newVDOM as VNode | undefined | Array<VNode | undefined | string>,\n );\n\n // 3) Append the newly created node(s)\n if (Array.isArray(newDom)) {\n for (const node of newDom) {\n if (node) {\n parentElement.appendChild(node);\n handleLifecycleEventsForOnMount(node as HTMLElement);\n }\n }\n } else if (newDom) {\n parentElement.appendChild(newDom);\n handleLifecycleEventsForOnMount(newDom as HTMLElement);\n }\n}\n",
|
|
10
|
-
"export type TransitionType =\n | \"fade\"\n | \"slide-left\"\n | \"slide-right\"\n | \"shake\"\n | \"none\";\n\nexport interface TransitionStyles {\n enter: Record<string, string>;\n enterActive: Record<string, string>;\n exit: Record<string, string>;\n exitActive: Record<string, string>;\n}\n\nexport type TransitionsEasing =\n | \"linear\"\n | \"ease\"\n | \"ease-in\"\n | \"ease-out\"\n | \"ease-in-out\"\n | \"step-start\"\n | \"step-end\";\n\nexport interface TransitionConfig {\n type?: TransitionType;\n styles?: TransitionStyles;\n duration?: number;\n easing?: TransitionsEasing | string;\n delay?: number;\n target?: \"parent\" | \"self\";\n}\n\nconst injectShakeKeyframes = (doc: Document | undefined) => {\n if (!doc) return;\n if (!doc.getElementById(\"defuss-shake\")) {\n const style = doc.createElement(\"style\");\n style.id = \"defuss-shake\";\n style.textContent =\n \"@keyframes shake{0%,100%{transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{transform:translate3d(-10px,0,0)}20%,40%,60%,80%{transform:translate3d(10px,0,0)}}\";\n doc.head.appendChild(style);\n }\n};\n\nexport const getTransitionStyles = (\n type: TransitionType,\n duration: number,\n easing = \"ease-in-out\",\n): TransitionStyles => {\n const t = `transform ${duration}ms ${easing}, opacity ${duration}ms ${easing}`;\n const styles: Record<string, TransitionStyles> = {\n fade: {\n enter: { opacity: \"0\", transition: t, transform: \"translate3d(0,0,0)\" },\n enterActive: { opacity: \"1\" },\n exit: { opacity: \"1\", transition: t, transform: \"translate3d(0,0,0)\" },\n exitActive: { opacity: \"0\" },\n },\n \"slide-left\": {\n enter: {\n transform: \"translate3d(100%,0,0)\",\n opacity: \"0.5\",\n transition: t,\n },\n enterActive: { transform: \"translate3d(0,0,0)\", opacity: \"1\" },\n exit: { transform: \"translate3d(0,0,0)\", opacity: \"1\", transition: t },\n exitActive: { transform: \"translate3d(-100%,0,0)\", opacity: \"0.5\" },\n },\n \"slide-right\": {\n enter: {\n transform: \"translate3d(-100%,0,0)\",\n opacity: \"0.5\",\n transition: t,\n },\n enterActive: { transform: \"translate3d(0,0,0)\", opacity: \"1\" },\n exit: { transform: \"translate3d(0,0,0)\", opacity: \"1\", transition: t },\n exitActive: { transform: \"translate3d(100%,0,0)\", opacity: \"0.5\" },\n },\n shake: (() => {\n injectShakeKeyframes(\n typeof document !== \"undefined\" ? document : undefined,\n );\n return {\n enter: {\n transform: \"translate3d(0,0,0)\",\n opacity: \"1\",\n transition: \"none\",\n },\n enterActive: {\n transform: \"translate3d(0,0,0)\",\n opacity: \"1\",\n animation: `shake ${duration}ms cubic-bezier(0.36,0.07,0.19,0.97)`,\n },\n exit: {\n transform: \"translate3d(0,0,0)\",\n opacity: \"1\",\n transition: \"none\",\n },\n exitActive: {\n transform: \"translate3d(0,0,0)\",\n opacity: \"1\",\n animation: `shake ${duration}ms cubic-bezier(0.36,0.07,0.19,0.97)`,\n },\n };\n })(),\n };\n return (\n styles[type] || { enter: {}, enterActive: {}, exit: {}, exitActive: {} }\n );\n};\n\nexport const applyStyles = (\n el: HTMLElement,\n styles: Record<string, string | number>,\n) =>\n Object.entries(styles).forEach(([k, v]) =>\n el.style.setProperty(k, String(v)),\n );\n\nexport const DEFAULT_TRANSITION_CONFIG: TransitionConfig = {\n type: \"fade\",\n duration: 300,\n easing: \"ease-in-out\",\n delay: 0,\n target: \"parent\",\n};\n\nconst wait = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nconst performCrossfade = async (\n element: HTMLElement,\n updateCallback: () => Promise<void>,\n duration: number,\n easing: string,\n): Promise<void> => {\n const originalStyle = element.style.cssText;\n const snapshot = element.cloneNode(true) as HTMLElement;\n // realm-safe: use the element's own document (works across windows / SSR DOMs)\n const doc = element.ownerDocument;\n\n try {\n const rect = element.getBoundingClientRect();\n\n // Position snapshot absolutely over original\n snapshot.style.cssText = `position:absolute;top:${rect.top}px;left:${rect.left}px;width:${rect.width}px;height:${rect.height}px;opacity:1;transition:opacity ${duration}ms ${easing};z-index:1000;`;\n\n // Prepare new content (initially hidden)\n element.style.opacity = \"0\";\n element.style.transition = `opacity ${duration}ms ${easing}`;\n\n // Insert snapshot and update content\n doc.body.appendChild(snapshot);\n await updateCallback();\n\n // Trigger simultaneous crossfade\n void element.offsetHeight;\n snapshot.style.opacity = \"0\";\n element.style.opacity = \"1\";\n\n await wait(duration);\n doc.body.removeChild(snapshot);\n } catch (error) {\n if (snapshot.parentElement) doc.body.removeChild(snapshot);\n throw error;\n } finally {\n element.style.cssText = originalStyle;\n }\n};\n\nexport const performTransition = async (\n element: HTMLElement,\n updateCallback: () => Promise<void>,\n config: TransitionConfig = {},\n): Promise<void> => {\n const {\n type = \"fade\",\n duration = 300,\n easing = \"ease-in-out\",\n delay = 0,\n } = { ...DEFAULT_TRANSITION_CONFIG, ...config };\n\n if (type === \"none\") {\n await updateCallback();\n return;\n }\n\n if (delay > 0) await wait(delay);\n\n // Use crossfade for fade transitions\n if (type === \"fade\") {\n await performCrossfade(element, updateCallback, duration, easing);\n return;\n }\n\n const styles = config.styles || getTransitionStyles(type, duration, easing);\n const originalTransition = element.style.transition;\n const originalAnimation = element.style.animation;\n\n try {\n // Clear any existing animation for shake restart\n if (type === \"shake\") {\n element.style.animation = \"none\";\n void element.offsetHeight;\n }\n\n // Apply exit transition\n applyStyles(element, styles.exit);\n void element.offsetHeight;\n applyStyles(element, styles.exitActive);\n\n await wait(duration);\n\n // Update content\n await updateCallback();\n\n // Apply enter transition\n applyStyles(element, styles.enter);\n void element.offsetHeight;\n applyStyles(element, styles.enterActive);\n\n await wait(duration);\n\n // Restore original styles\n element.style.transition = originalTransition;\n element.style.animation = originalAnimation;\n } catch (error) {\n element.style.transition = originalTransition;\n element.style.animation = originalAnimation;\n throw error;\n }\n};\n",
|
|
11
|
-
"
|
|
12
|
-
"import
|
|
5
|
+
"/**\n * Wraps `cb` so each call runs it in a microtask, with the same arguments.\n * VERIFIED: renderer.test.ts asserts onMount has not run before that microtask.\n */\nexport const queueCallback = <T extends any[]>(cb: (...args: T) => void) => (...args: T) =>\n queueMicrotask(() => cb(...args));\n",
|
|
6
|
+
"export type DelegatedPhase = \"bubble\" | \"capture\";\n\n/** Options of {@link registerDelegatedEvent}. */\nexport interface DelegatedEventOptions {\n capture?: boolean;\n /** If true, allows multiple handlers per element+type (Dequery mode) */\n multi?: boolean;\n}\n\nexport interface ParsedEventProp {\n eventType: string;\n capture: boolean;\n}\n\n/**\n * Events whose handlers are forced into the capture phase, so an ancestor's\n * handler also sees descendants' events (container onFocus/onBlur). Every\n * other non-bubbling event reaches only its target's handlers, natively.\n */\nexport const CAPTURE_ONLY_EVENTS = new Set<string>([\n \"focus\",\n \"blur\",\n \"scroll\",\n \"mouseenter\",\n \"mouseleave\",\n // Note: focusin/focusout DO bubble, so they're not included here\n]);\n\n/**\n * Why per-element native listeners instead of one delegating root listener:\n * replaying the event path from the document ran handlers in the wrong order\n * relative to native listeners, ignored an ancestor's stopPropagation(), missed\n * non-bubbling events and reported currentTarget === document. On the element\n * itself the browser applies every propagation rule exactly.\n * VERIFIED: order, stopPropagation (both phases), stopImmediatePropagation,\n * currentTarget, non-bubbling and shadow DOM (delegated-events.browser.test.ts).\n *\n * What stays \"delegated\" is the indirection: a JSX prop slot owns one\n * trampoline listener that calls whichever handler the slot holds right now,\n * so re-renders swap handlers without touching listeners. Multi-mode handlers\n * (dequery-style on()) are attached as-is.\n */\ninterface HandlerEntry {\n bubble?: EventListener;\n capture?: EventListener;\n bubbleSet?: Set<EventListener>;\n captureSet?: Set<EventListener>;\n}\n\n/** element -> (eventType -> handlers) */\nconst elementHandlerMap = new WeakMap<EventTarget, Map<string, HandlerEntry>>();\n\n/** element -> (`${eventType}:${phase}` -> installed slot trampoline) */\nconst slotListeners = new WeakMap<EventTarget, Map<string, EventListener>>();\n\n/**\n * Re-entrancy guard for JSX slots: while a slot's handler runs, a *new* event\n * of the same type that morph fires synchronously on the same element (e.g.\n * focus/blur while moving nodes) does not re-enter it.\n */\nconst activeDispatches = new WeakMap<EventTarget, Set<string>>();\n\n/**\n * Parses a JSX event prop name: `onClick` gives `{ eventType: \"click\", capture: false }`,\n * `onClickCapture` the capture phase. Case-insensitive; `null` for anything not starting with `on`.\n */\nexport const parseEventPropName = (\n propName: string,\n): ParsedEventProp | null => {\n if (!propName.startsWith(\"on\")) return null;\n\n // support onClick / onClickCapture / onclick / onclickcapture\n const raw = propName.slice(2);\n if (!raw) return null;\n\n const lower = raw.toLowerCase();\n const isCapture = lower.endsWith(\"capture\");\n\n const eventType = isCapture ? lower.slice(0, -\"capture\".length) : lower;\n\n if (!eventType) return null;\n\n return { eventType, capture: isCapture };\n};\n\nconst getOrCreateElementHandlers = (el: EventTarget) => {\n const existing = elementHandlerMap.get(el);\n if (existing) return existing;\n\n const created = new Map<string, HandlerEntry>();\n elementHandlerMap.set(el, created);\n return created;\n};\n\n/** Run the handler a JSX slot holds right now (looked up per event). */\nconst runSlot = (\n target: EventTarget,\n eventType: string,\n phase: DelegatedPhase,\n event: Event,\n): void => {\n const handler = elementHandlerMap.get(target)?.get(eventType)?.[phase];\n if (!handler) return;\n\n const dispatchKey = `${eventType}:${phase}`;\n let active = activeDispatches.get(target);\n if (active?.has(dispatchKey)) return;\n if (!active) {\n active = new Set();\n activeDispatches.set(target, active);\n }\n active.add(dispatchKey);\n try {\n handler.call(target, event);\n } finally {\n active.delete(dispatchKey);\n }\n};\n\n/** Set (or clear) a JSX slot, installing/removing its trampoline listener. */\nconst setSlot = (\n target: EventTarget,\n eventType: string,\n phase: DelegatedPhase,\n entry: HandlerEntry,\n handler: EventListener | undefined,\n): void => {\n entry[phase] = handler;\n const key = `${eventType}:${phase}`;\n const capture = phase === \"capture\";\n let byKey = slotListeners.get(target);\n const installed = byKey?.get(key);\n\n if (handler && !installed) {\n if (!byKey) {\n byKey = new Map();\n slotListeners.set(target, byKey);\n }\n const trampoline: EventListener = (event) =>\n runSlot(target, eventType, phase, event);\n byKey.set(key, trampoline);\n target.addEventListener(eventType, trampoline, capture);\n } else if (!handler && installed) {\n byKey!.delete(key);\n target.removeEventListener(eventType, installed, capture);\n }\n};\n\n/** Detach every handler of one phase (slot and set) for a type. */\nconst clearPhase = (\n target: EventTarget,\n eventType: string,\n entry: HandlerEntry,\n phase: DelegatedPhase,\n): void => {\n setSlot(target, eventType, phase, entry, undefined);\n const setKey = phase === \"capture\" ? \"captureSet\" : \"bubbleSet\";\n for (const handler of entry[setKey] ?? [])\n target.removeEventListener(eventType, handler, phase === \"capture\");\n entry[setKey] = undefined;\n};\n\n/**\n * Attaches `handler` to `element` the way JSX props do: one slot per event type and phase, so\n * registering again replaces the handler without adding a listener. With `{ multi: true }`\n * every handler becomes its own native listener (dequery-style `on()`). `focus`, `blur`,\n * `scroll`, `mouseenter` and `mouseleave` always use the capture phase.\n */\nexport const registerDelegatedEvent = (\n element: HTMLElement,\n eventType: string,\n handler: EventListener,\n options: DelegatedEventOptions = {},\n): void => {\n // capture-only events should be forced to capture\n const capture = options.capture || CAPTURE_ONLY_EVENTS.has(eventType);\n const phase: DelegatedPhase = capture ? \"capture\" : \"bubble\";\n\n const byEvent = getOrCreateElementHandlers(element);\n const entry = byEvent.get(eventType) ?? {};\n byEvent.set(eventType, entry);\n\n if (options.multi) {\n // Dequery mode: every handler is its own native listener (the set mirrors\n // addEventListener's dedupe of an identical type/handler/capture triple)\n const setKey = capture ? \"captureSet\" : \"bubbleSet\";\n const set = (entry[setKey] ??= new Set());\n if (!set.has(handler)) {\n set.add(handler);\n element.addEventListener(eventType, handler, capture);\n }\n } else {\n // JSX mode: one handler per prop, overwrite to prevent duplicates\n setSlot(element, eventType, phase, entry, handler);\n }\n};\n\n/** true when a handler entry holds no single handler and no non-empty set */\nconst isEntryEmpty = (entry: HandlerEntry): boolean =>\n !entry.capture &&\n !entry.bubble &&\n (!entry.captureSet || entry.captureSet.size === 0) &&\n (!entry.bubbleSet || entry.bubbleSet.size === 0);\n\n/**\n * Removes `handler` (from both phases), or every handler of `eventType` when no handler is given.\n */\nexport const removeDelegatedEvent = (\n target: EventTarget,\n eventType: string,\n handler?: EventListener,\n // part of the public signature; removal always covers both phases,\n // so the options are intentionally not consulted here\n _options: DelegatedEventOptions = {},\n): void => {\n const byEvent = elementHandlerMap.get(target);\n if (!byEvent) return;\n\n const entry = byEvent.get(eventType);\n if (!entry) return;\n\n if (handler) {\n // Remove the specific handler from both phases (the caller may not know which)\n for (const phase of [\"capture\", \"bubble\"] as const) {\n const set = phase === \"capture\" ? entry.captureSet : entry.bubbleSet;\n if (set?.delete(handler))\n target.removeEventListener(eventType, handler, phase === \"capture\");\n if (entry[phase] === handler)\n setSlot(target, eventType, phase, entry, undefined);\n }\n } else {\n // Remove ALL handlers for this event type (both phases)\n // This is what users expect from .off(\"click\") without specific handler\n clearPhase(target, eventType, entry, \"capture\");\n clearPhase(target, eventType, entry, \"bubble\");\n }\n\n // Clean up entry if empty\n if (isEntryEmpty(entry)) {\n byEvent.delete(eventType);\n }\n};\n\n/** Teardown hooks of listener owners outside this registry. */\nconst clearHooks = new Set<(target: EventTarget) => void>();\n\n/**\n * Why: listeners a facade attaches natively (defuss-query's on()) live\n * outside this registry, yet must go whenever morph clears an element\n * (removal, replacement, clearDelegatedEventsDeep). A hook keeps morph\n * ignorant of who owns them, instead of morph also tracking native listeners.\n * Registering the same hook twice is a no-op; returns an unregister function.\n */\nexport const onClearDelegatedEvents = (\n hook: (target: EventTarget) => void,\n): (() => void) => {\n clearHooks.add(hook);\n return () => {\n clearHooks.delete(hook);\n };\n};\n\n/** Removes every registered handler of one element and runs the {@link onClearDelegatedEvents} hooks for it. */\nexport const clearDelegatedEvents = (target: EventTarget): void => {\n const byEvent = elementHandlerMap.get(target);\n if (byEvent) {\n for (const [eventType, entry] of byEvent) {\n clearPhase(target, eventType, entry, \"capture\");\n clearPhase(target, eventType, entry, \"bubble\");\n }\n byEvent.clear();\n }\n for (const hook of clearHooks) hook(target);\n};\n\n/**\n * Clear delegated events for an element and all its descendants. Morph runs\n * it on every element it removes or replaces; facades call it before removing\n * nodes themselves (defuss-query does in its internal remove()).\n */\nexport const clearDelegatedEventsDeep = (root: HTMLElement): void => {\n // Clear the root element\n clearDelegatedEvents(root);\n\n // Walk all descendant elements and clear their handlers\n // Use ownerDocument for SSR/multi-doc compatibility\n const doc = root.ownerDocument;\n if (!doc) return;\n const walker = doc.createTreeWalker(root, 1 /* NodeFilter.SHOW_ELEMENT */);\n let node = walker.nextNode();\n while (node) {\n clearDelegatedEvents(node as HTMLElement);\n node = walker.nextNode();\n }\n};\n\n/**\n * Get all event types currently registered on an element.\n * Used to detect which events need to be removed when vnode props change.\n */\nexport const getRegisteredEventTypes = (element: HTMLElement): Set<string> => {\n const byEvent = elementHandlerMap.get(element);\n if (!byEvent) return new Set();\n return new Set(byEvent.keys());\n};\n\n/**\n * Get all event keys with phases currently registered on an element.\n * Returns keys like \"click:bubble\", \"click:capture\" for precise phase-aware removal.\n */\nexport const getRegisteredEventKeys = (element: HTMLElement): Set<string> => {\n const byEvent = elementHandlerMap.get(element);\n if (!byEvent) return new Set();\n\n const keys = new Set<string>();\n for (const [eventType, entry] of byEvent) {\n if (entry.bubble || entry.bubbleSet?.size) keys.add(`${eventType}:bubble`);\n if (entry.capture || entry.captureSet?.size)\n keys.add(`${eventType}:capture`);\n }\n return keys;\n};\n\n/**\n * Remove delegated event handler for a specific phase only.\n * Used by patchElementInPlace to precisely remove stale handlers when vnode changes from\n * onClick + onClickCapture → onClickCapture only.\n */\nexport const removeDelegatedEventByKey = (\n element: HTMLElement,\n eventType: string,\n phase: \"bubble\" | \"capture\",\n): void => {\n const byEvent = elementHandlerMap.get(element);\n if (!byEvent) return;\n\n const entry = byEvent.get(eventType);\n if (!entry) return;\n\n clearPhase(element, eventType, entry, phase);\n\n // Clean up entry if empty\n if (isEntryEmpty(entry)) byEvent.delete(eventType);\n};\n",
|
|
7
|
+
"import type { VNode, VNodeAttributes } from \"./types.js\";\n\n/**\n * Marks VNodes derived from existing DOM (HTML strings / DOM nodes).\n * Such VNodes cannot declare event handlers, so the morph engine must\n * preserve delegated handlers already attached to surviving elements\n * (same rationale as uncontrolled form-state preservation).\n */\nexport const FROM_DOM_MARKER: unique symbol = Symbol(\"defuss-morph.from-dom\");\n\n/**\n * VNode type of an HTML comment: `{ type: \"#comment\", value }`.\n * Why \"#comment\": it is the DOM's own nodeName for comments and can never\n * collide with a tag name (\"#\" is invalid there). The data lives in `value`,\n * not `children`, so generic tree walkers never mistake it for content.\n */\nexport const COMMENT_TYPE = \"#comment\";\n\nexport type CommentVNode = VNode & { type: typeof COMMENT_TYPE };\n\n/** True for a comment VNode (`{ type: \"#comment\", value }`). */\nexport const isCommentVNode = (value: unknown): value is CommentVNode =>\n !!value &&\n typeof value === \"object\" &&\n (value as VNode).type === COMMENT_TYPE;\n\nconst HTML_BOOLEAN_ATTRIBUTES = new Set([\n \"allowfullscreen\",\n \"async\",\n \"autofocus\",\n \"autoplay\",\n \"checked\",\n \"controls\",\n \"default\",\n \"defer\",\n \"disabled\",\n \"formnovalidate\",\n \"hidden\",\n \"inert\",\n \"ismap\",\n \"itemscope\",\n \"loop\",\n \"multiple\",\n \"muted\",\n \"nomodule\",\n \"novalidate\",\n \"open\",\n \"playsinline\",\n \"readonly\",\n \"required\",\n \"reversed\",\n \"selected\",\n]);\n\nconst domAttributeToVNodeValue = (attr: Attr): string | boolean =>\n HTML_BOOLEAN_ATTRIBUTES.has(attr.name.toLowerCase()) ? true : attr.value;\n\n/** Parses `input` into a detached document with the given parser. */\nexport function parseDOM(\n input: string,\n type: DOMParserSupportedType,\n Parser: typeof DOMParser,\n): Document {\n return new Parser().parseFromString(input, type);\n}\n\n/** True when `input` parses as an SVG document (root element `<svg>`). */\nexport function isSVG(input: string, Parser: typeof DOMParser) {\n const doc = parseDOM(input, \"image/svg+xml\", Parser);\n if (!doc.documentElement) return false;\n return doc.documentElement.nodeName.toLowerCase() === \"svg\";\n}\n\n/** True when `input` parses into at least one element besides the implied `<head>` and `<body>`. */\nexport function isHTML(input: string, Parser: typeof DOMParser): boolean {\n const doc = parseDOM(input, \"text/html\", Parser);\n return doc.documentElement.querySelectorAll(\"*\").length > 2; // 2 = <html> and <body>\n}\n\n/** True when `input` contains a tag and parses as HTML or SVG. */\nexport const isMarkup = (input: string, Parser: typeof DOMParser): boolean =>\n input.indexOf(\"<\") > -1 &&\n input.indexOf(\">\") > -1 &&\n (isHTML(input, Parser) || isSVG(input, Parser));\n\n/** Parses `markup` (HTML or SVG) and returns its top-level nodes, detached from any live document. */\nexport function renderMarkup(\n markup: string,\n Parser: typeof DOMParser,\n doc?: Document,\n) {\n const parsed = doc ? doc : parseDOM(markup, getMimeType(markup, Parser), Parser);\n // HTML documents expose body; XML documents (e.g. image/svg+xml) don't —\n // there the documentElement is the root node to render\n if (parsed.body) return Array.from(parsed.body.childNodes);\n return parsed.documentElement ? [parsed.documentElement] : [];\n}\n\n/** The `DOMParser` MIME type for `input`: `image/svg+xml` for SVG documents, else `text/html`. */\nexport function getMimeType(\n input: string,\n Parser: typeof DOMParser,\n): DOMParserSupportedType {\n if (isSVG(input, Parser)) {\n return \"image/svg+xml\";\n }\n return \"text/html\";\n}\n\n/**\n * The content fragment of a `<template>` element, where the parser puts its markup; `undefined` for other elements.\n * morph reads, creates and patches a template's children there, so markup such as defuss-i18n's translation\n * templates survives a morph.\n */\nexport const templateContent = (element: Element): DocumentFragment | undefined =>\n element.localName === \"template\" ? (element as HTMLTemplateElement).content : undefined;\n\n/**\n * Converts a DOM node to a VNode structure for use with updateDomWithVdom.\n * This allows us to leverage the sophisticated partial update system even for Node inputs.\n */\nexport function domNodeToVNode(node: Node): VNode<VNodeAttributes> | string {\n if (node.nodeType === 3 /* Node.TEXT_NODE */) {\n return node.nodeValue || \"\";\n }\n\n if (node.nodeType === 1 /* Node.ELEMENT_NODE */) {\n const element = node as Element;\n const attributes: VNodeAttributes & { [FROM_DOM_MARKER]?: true } = {};\n\n // Convert DOM attributes to VNode attributes\n for (let i = 0; i < element.attributes.length; i++) {\n const attr = element.attributes[i];\n attributes[attr.name] = domAttributeToVNodeValue(attr);\n }\n\n // Convert child nodes recursively; a <template> keeps its markup in .content, not in childNodes\n // (VERIFIED: reading childNodes turned `<template><b>x</b></template>` into an empty template)\n const children: Array<VNode<VNodeAttributes> | string> = [];\n for (let child = (templateContent(element) ?? element).firstChild; child; child = child.nextSibling) {\n children.push(domNodeToVNode(child));\n }\n attributes[FROM_DOM_MARKER] = true;\n\n // localName is the name the parser gave the element: lowercase for HTML, camelCase where SVG has it\n // (VERIFIED: tagName.toLowerCase() turned linearGradient into an unknown \"lineargradient\", morph.test.ts)\n return { type: element.localName, attributes, children };\n }\n\n if (node.nodeType === 8 /* Node.COMMENT_NODE */) {\n return { type: COMMENT_TYPE, value: node.nodeValue ?? \"\" };\n }\n\n // For other node types (processing instructions, etc.), convert to empty string\n return \"\";\n}\n\n/**\n * One inert document per DOMParser, which creates the <template> each fragment parses into. VERIFIED (A/B in\n * Chromium, 2026-11-01): creating a document per call made 500 small re-renders take half again as long; the\n * document only ever creates detached templates, so reusing it changes no result.\n */\nconst inertDocuments = new WeakMap<typeof DOMParser, Document>();\n\n/** Input starting (after optional comments) with doctype/html/head/body. */\nconst DOCUMENT_START = /^\\s*(?:<!--[\\s\\S]*?-->\\s*)*<(?:!doctype|html|head|body)[\\s>/]/i;\n\n/**\n * Converts an HTML string to VNode structure for use with updateDomWithVdom.\n * This allows markup strings to benefit from the intelligent partial update system.\n */\nexport function htmlStringToVNodes(\n html: string,\n Parser: typeof DOMParser,\n): Array<VNode<VNodeAttributes> | string> {\n // A full document parses as one, so its <head> content (e.g. <title>) never\n // leaks into the result.\n if (DOCUMENT_START.test(html)) {\n return toVNodes(new Parser().parseFromString(html, \"text/html\").body.childNodes);\n }\n\n // A fragment parses as <template> content, the parser's context-free mode.\n // VERIFIED: in Chromium and happy-dom (html.test.ts), inside <body> the\n // parser drops table tags, so `<tr><td>x</td></tr>` became the text \"x\", and a\n // leading comment without a <body> landed outside it and was lost. Template\n // content keeps both, and stays inert (no scripts run, nothing loads).\n let inert = inertDocuments.get(Parser);\n if (!inert) {\n inert = new Parser().parseFromString(\"\", \"text/html\");\n inertDocuments.set(Parser, inert);\n }\n const template = inert.createElement(\"template\");\n template.innerHTML = html;\n return toVNodes(template.content.childNodes);\n}\n\nfunction toVNodes(nodes: NodeListOf<ChildNode>): Array<VNode<VNodeAttributes> | string> {\n const vNodes: Array<VNode<VNodeAttributes> | string> = [];\n for (let i = 0; i < nodes.length; i++) {\n const vnode = domNodeToVNode(nodes[i]);\n if (vnode !== \"\") vNodes.push(vnode);\n }\n return vNodes;\n}\n",
|
|
8
|
+
"import type {\n DomAbstractionImpl,\n RenderInput,\n VNode,\n VNodeAttributes,\n VNodeChildren,\n} from \"./types.js\";\nimport { queueCallback } from \"./queue.js\";\nimport {\n parseEventPropName,\n registerDelegatedEvent,\n} from \"./delegated-events.js\";\nimport { isCommentVNode, templateContent } from \"./html.js\";\n\nexport const CLASS_ATTRIBUTE_NAME = \"class\";\nexport const XLINK_ATTRIBUTE_NAME = \"xlink\";\nexport const XMLNS_ATTRIBUTE_NAME = \"xmlns\";\nexport const REF_ATTRIBUTE_NAME = \"ref\";\nexport const DANGEROUSLY_SET_INNER_HTML_ATTRIBUTE = \"dangerouslySetInnerHTML\";\n\nexport const nsMap = {\n [XMLNS_ATTRIBUTE_NAME]: \"http://www.w3.org/2000/xmlns/\",\n [XLINK_ATTRIBUTE_NAME]: \"http://www.w3.org/1999/xlink\",\n svg: \"http://www.w3.org/2000/svg\",\n};\n\n/**\n * Calls `onUnmount` once `domNode` leaves the document. A move (removal and re-insertion in the\n * same task) is not an unmount: the observer follows the node to its new parent. Throws when the\n * node has no parent; a no-op where `MutationObserver` does not exist (SSR).\n */\nexport const observeUnmount = (domNode: Node, onUnmount: () => void): void => {\n if (!domNode || typeof onUnmount !== \"function\") {\n throw new Error(\n \"Invalid arguments. Ensure domNode and onUnmount are valid.\",\n );\n }\n\n // Skip MutationObserver in SSR environments where it doesn't exist\n if (typeof MutationObserver === \"undefined\") {\n return;\n }\n\n let parentNode: Node | null = domNode.parentNode;\n if (!parentNode) {\n throw new Error(\"The provided domNode does not have a parentNode.\");\n }\n\n const observer = new MutationObserver((mutationsList) => {\n for (const mutation of mutationsList) {\n if (mutation.removedNodes.length > 0) {\n for (const removedNode of mutation.removedNodes) {\n if (removedNode === domNode) {\n // Defer check: if node is re-inserted (move), it will be connected\n queueMicrotask(() => {\n if (!domNode.isConnected) {\n // Node was actually unmounted\n onUnmount();\n observer.disconnect();\n return;\n }\n\n // Node was moved, not unmounted: re-arm observer on new parent\n const newParent = domNode.parentNode;\n if (newParent && newParent !== parentNode) {\n parentNode = newParent;\n observer.disconnect();\n observer.observe(parentNode, { childList: true });\n }\n });\n return;\n }\n }\n }\n }\n });\n\n // Observe the parentNode for child removals\n observer.observe(parentNode, { childList: true });\n};\n\n/** Elements with an armed unmount observer (at most one per element). */\nconst unmountObserved = new WeakSet<Node>();\n\n/**\n * Runs the pending `onMount` hook and arms the `onUnmount` observer of an\n * element that was just inserted or patched in place.\n *\n * Why one observer that reads `$onUnmount` when it fires: morph calls this on\n * every in-place patch, and each re-render sets a fresh `onUnmount` closure.\n * Arming one observer per call made a single removal run every handler ever\n * registered (VERIFIED: 1 render + 3 morphs fired onUnmount 10 times).\n */\nexport const handleLifecycleEventsForOnMount = (newEl: HTMLElement) => {\n // check for a lifecycle \"onMount\" hook and call it\n if (typeof (newEl as any)?.$onMount === \"function\") {\n (newEl as any).$onMount!(newEl); // remove the hook after it's been called\n (newEl as any).$onMount = null;\n }\n\n if (typeof (newEl as any)?.$onUnmount === \"function\" && !unmountObserved.has(newEl)) {\n unmountObserved.add(newEl);\n observeUnmount(newEl, () => {\n // re-arm on a later re-insertion of the same node\n unmountObserved.delete(newEl);\n // the element, as UnmountHandler declares (it was called without one until 0.3.0)\n (newEl as any).$onUnmount?.(newEl);\n });\n }\n};\n\n/**\n * Returns the VNode-to-DOM renderer for `document`: element and SVG creation, text and comment\n * nodes, attributes (class arrays, style objects, controlled form props, namespaced SVG\n * attributes), refs, JSX event props and the `onMount`/`onUnmount` hooks.\n */\nexport const getRenderer = (document: Document): DomAbstractionImpl => {\n // DOM abstraction layer for manipulation\n const renderer = {\n hasElNamespace: (domElement: Element | Document): boolean =>\n (domElement as Element).namespaceURI === nsMap.svg,\n\n hasSvgNamespace: (\n parentElement: Element | Document,\n type: string,\n ): boolean =>\n renderer.hasElNamespace(parentElement) &&\n type !== \"STYLE\" &&\n type !== \"SCRIPT\",\n\n createElementOrElements: (\n virtualNode: RenderInput,\n parentDomElement?: Element | Document,\n ): Array<Element | Text | undefined> | Element | Text | undefined => {\n if (Array.isArray(virtualNode)) {\n return renderer.createChildElements(virtualNode, parentDomElement);\n }\n // text input is a text node, as in createChildElements (createElement\n // used to take it as a tag name: \"hello\" became <hello>)\n if (typeof virtualNode === \"string\" || typeof virtualNode === \"number\") {\n return renderer.createTextNode(String(virtualNode), parentDomElement);\n }\n if (typeof virtualNode !== \"undefined\") {\n return renderer.createElement(virtualNode, parentDomElement);\n }\n // undefined virtualNode -> e.g. when a tsx variable is used in markup which is undefined\n return renderer.createTextNode(\"\", parentDomElement);\n },\n\n createElement: (\n virtualNode: RenderInput,\n parentDomElement?: Element | Document,\n ): Element | undefined => {\n let newEl: Element | undefined;\n\n // VERIFIED: comment nodes are leaves in the DOM (no attributes or\n // children), so none of the element setup below applies\n if (isCommentVNode(virtualNode)) {\n const comment = document.createComment(virtualNode.value ?? \"\");\n parentDomElement?.appendChild(comment);\n return comment as unknown as Element;\n }\n\n // An async function component that is still a function never resolved:\n // the JSX runtime failed while producing it, so render an empty box.\n if (\n typeof virtualNode === \"function\" &&\n virtualNode.constructor.name === \"AsyncFunction\"\n ) {\n newEl = document.createElement(\"div\");\n } else if (\n typeof virtualNode === \"object\" &&\n virtualNode !== null &&\n \"type\" in virtualNode\n ) {\n const vNode = virtualNode as VNode;\n\n if (typeof vNode.type === \"function\") {\n newEl = document.createElement(\"div\");\n (newEl as HTMLElement).innerText =\n `FATAL ERROR: ${(vNode.type as { _error?: string })._error}`;\n } else if (\n // SVG support\n (typeof vNode.type === \"string\" &&\n vNode.type.toUpperCase() === \"SVG\") ||\n (parentDomElement &&\n renderer.hasSvgNamespace(\n parentDomElement,\n typeof vNode.type === \"string\" ? vNode.type.toUpperCase() : \"\",\n ))\n ) {\n newEl = document.createElementNS(nsMap.svg, vNode.type as string);\n } else {\n newEl = document.createElement(vNode.type as string);\n }\n\n if (vNode.attributes) {\n renderer.setAttributes(vNode, newEl as Element);\n\n // apply dangerouslySetInnerHTML if provided\n if (vNode.attributes.dangerouslySetInnerHTML) {\n (newEl as HTMLElement).innerHTML =\n vNode.attributes.dangerouslySetInnerHTML.__html;\n }\n }\n\n // Skip child creation when dangerouslySetInnerHTML is used (matches React semantics)\n if (vNode.children && !vNode.attributes?.dangerouslySetInnerHTML) {\n // a <template>'s children belong in its content fragment, as the HTML parser puts them\n renderer.createChildElements(\n vNode.children,\n (templateContent(newEl) as unknown as Element | undefined) ?? newEl,\n );\n }\n }\n // anything else (text, null, a plain object) is not an element: undefined\n\n // Errors propagate to the caller unchanged: a library that logs and\n // rethrows reports every failure twice and cannot be silenced.\n if (newEl && parentDomElement) {\n parentDomElement.appendChild(newEl);\n handleLifecycleEventsForOnMount(newEl as HTMLElement);\n }\n return newEl as Element;\n },\n\n createTextNode: (text: string, domElement?: Element | Document): Text => {\n const node = document.createTextNode(text.toString());\n\n if (domElement) {\n domElement.appendChild(node);\n }\n return node;\n },\n\n createChildElements: (\n virtualChildren: VNodeChildren,\n domElement?: Element | Document,\n ): Array<Element | Text | undefined> => {\n const children: Array<Element | Text | undefined> = [];\n\n for (let i = 0; i < virtualChildren.length; i++) {\n const virtualChild = virtualChildren[i];\n\n // Skip booleans entirely - {true} and {false} render nothing (React/JSX semantics)\n if (typeof virtualChild === \"boolean\") {\n continue;\n }\n\n if (\n virtualChild === null ||\n (typeof virtualChild !== \"object\" &&\n typeof virtualChild !== \"function\")\n ) {\n children.push(\n renderer.createTextNode(\n (typeof virtualChild === \"undefined\" || virtualChild === null\n ? \"\"\n : virtualChild!\n ).toString(),\n domElement,\n ),\n );\n } else {\n children.push(\n renderer.createElement(virtualChild as VNode, domElement),\n );\n }\n }\n return children;\n },\n\n setAttribute: (name: string, value: any, domElement: Element) => {\n // attributes not set (undefined) are ignored; use null value to reset an attributes state\n if (typeof value === \"undefined\") return;\n\n if (name === DANGEROUSLY_SET_INNER_HTML_ATTRIBUTE) return;\n\n // internal list key: store on element, do not serialize into DOM\n if (name === \"key\") {\n (domElement as HTMLElement & { _defussKey?: string })._defussKey =\n String(value);\n return;\n }\n\n // save ref as { current: DOMElement } in ref object. A ref needs no\n // unmount observer: an earlier no-op one replaced an onUnmount declared\n // before `ref` (VERIFIED: it never fired) and added observers per morph.\n if (name === REF_ATTRIBUTE_NAME && typeof value !== \"function\") {\n (value as { current?: unknown }).current = domElement;\n (domElement as any)._defussRef = value;\n return;\n }\n\n // event props: delegate globally; still keep defuss lifecycle hooks\n const parsed = parseEventPropName(name);\n if (parsed && typeof value === \"function\") {\n const { eventType, capture } = parsed;\n\n if (eventType === \"mount\") {\n (domElement as any).$onMount = queueCallback(value as () => void);\n return;\n }\n\n // latest wins, like event props: a re-render replaces the handler\n // instead of chaining it to every earlier render's closure\n if (eventType === \"unmount\") {\n (domElement as any).$onUnmount = queueCallback(value as () => void);\n return;\n }\n\n registerDelegatedEvent(\n domElement as HTMLElement,\n eventType,\n value as EventListener,\n { capture },\n );\n return;\n }\n\n // transforms className=\"...\" -> class=\"...\"\n if (name === \"className\") {\n name = CLASS_ATTRIBUTE_NAME;\n }\n\n // transforms class={['a', 'b']} into class=\"a b\"\n if (name === CLASS_ATTRIBUTE_NAME && Array.isArray(value)) {\n value = value.filter((val) => !!val).join(\" \");\n }\n\n // SVG support\n const nsEndIndex = name.match(/[A-Z]/)?.index;\n if (renderer.hasElNamespace(domElement) && nsEndIndex) {\n const ns = name.substring(0, nsEndIndex).toLowerCase();\n const attrName = name.substring(nsEndIndex, name.length).toLowerCase();\n const namespace = nsMap[ns as keyof typeof nsMap] || null;\n domElement.setAttributeNS(\n namespace,\n ns === XLINK_ATTRIBUTE_NAME || ns === XMLNS_ATTRIBUTE_NAME\n ? `${ns}:${attrName}`\n : name,\n String(value),\n );\n } else if (name === \"style\" && typeof value !== \"string\") {\n const styleObj = value as Record<string, string | number>;\n for (const prop of Object.keys(styleObj)) {\n (domElement as HTMLElement).style[prop as any] = String(\n styleObj[prop],\n );\n }\n } else if (typeof value === \"boolean\") {\n (domElement as any)[name] = value;\n // Also set/remove the attribute so SSG serialization includes it\n if (value) {\n domElement.setAttribute(name, \"\");\n } else {\n domElement.removeAttribute(name);\n }\n } else if (\n // Controlled input props: use property assignment for live value,\n // AND setAttribute so SSG serialization (w3c-xmlserializer) includes it\n (name === \"value\" || name === \"checked\" || name === \"selectedIndex\") &&\n (domElement.nodeName === \"INPUT\" ||\n domElement.nodeName === \"TEXTAREA\" ||\n domElement.nodeName === \"SELECT\")\n ) {\n (domElement as any)[name] = value;\n if (name === \"checked\") {\n if (value) {\n domElement.setAttribute(\"checked\", \"\");\n } else {\n domElement.removeAttribute(\"checked\");\n }\n } else if (name === \"value\") {\n domElement.setAttribute(\"value\", String(value));\n }\n // selectedIndex has no HTML attribute equivalent - skip setAttribute\n } else {\n domElement.setAttribute(name, String(value));\n }\n },\n\n setAttributes: (\n virtualNode: VNode<VNodeAttributes>,\n domElement: Element,\n ) => {\n // attributes are optional on hand-written VNodes — guard instead of the\n // `!` assertion, which crashed patching an element with an\n // attributes-less vnode (Object.keys(undefined) throws)\n const attrNames = Object.keys(virtualNode.attributes ?? {});\n for (let i = 0; i < attrNames.length; i++) {\n renderer.setAttribute(\n attrNames[i],\n virtualNode.attributes![attrNames[i]],\n domElement,\n );\n }\n },\n };\n return renderer;\n};\n",
|
|
9
|
+
"/**\n * Marks one longest strictly increasing subsequence of `values`, skipping negative entries (never marked).\n * Patience sorting with back links: O(n log n) time, three typed arrays of n entries.\n *\n * Why: a morph keeps the matched nodes whose old positions already increase in the new order where they are and moves\n * only the others. The longest such run means the fewest moves: every node outside it would be out of order\n * otherwise, and any node left out of it must move. VERIFIED: morph-reorder.test.ts counts the moves against an\n * independent quadratic count, for the everyday operations and for random keyed edits.\n */\nexport const longestIncreasingRun = (values: ArrayLike<number>): Uint8Array => {\n const n = values.length;\n const marked = new Uint8Array(n);\n // tails[k]: the index of the smallest last value of an increasing run of length k + 1 found so far\n const tails = new Int32Array(n);\n const previous = new Int32Array(n);\n let length = 0;\n\n for (let i = 0; i < n; i++) {\n const value = values[i];\n if (value < 0) continue;\n let low = 0;\n let high = length;\n while (low < high) {\n const mid = (low + high) >> 1;\n if (values[tails[mid]] < value) low = mid + 1;\n else high = mid;\n }\n previous[i] = low > 0 ? tails[low - 1] : -1;\n tails[low] = i;\n if (low === length) length++;\n }\n\n for (let i = length > 0 ? tails[length - 1] : -1; i >= 0; i = previous[i]) marked[i] = 1;\n return marked;\n};\n",
|
|
10
|
+
"import type {\n Globals,\n RenderInput,\n VNode,\n VNodeAttributes,\n VNodeChild,\n} from \"./types.js\";\nimport {\n getRenderer,\n handleLifecycleEventsForOnMount,\n} from \"./renderer.js\";\nimport { isCommentVNode, templateContent } from \"./html.js\";\nimport { longestIncreasingRun } from \"./lis.js\";\nimport {\n clearDelegatedEventsDeep,\n getRegisteredEventKeys,\n parseEventPropName,\n removeDelegatedEventByKey,\n} from \"./delegated-events.js\";\nimport { FROM_DOM_MARKER } from \"./html.js\";\n\n/**\n * Compares two DOM nodes for equality with performance optimizations.\n * 1. Checks for reference equality.\n * 2. Compares node types.\n * 3. For Element nodes, compares tag names and attributes.\n * 4. For Text and Comment nodes, compares their data.\n */\nexport const areDomNodesEqual = (oldNode: Node, newNode: Node): boolean => {\n // return true if both references are identical\n if (oldNode === newNode) return true;\n\n // compare node types\n if (oldNode.nodeType !== newNode.nodeType) return false;\n\n // handle Element nodes\n if (oldNode.nodeType === 1 /* Node.ELEMENT_NODE */) {\n const oldElement = oldNode as Element;\n const newElement = newNode as Element;\n\n // compare tag names\n if (oldElement.tagName !== newElement.tagName) return false;\n\n const oldAttrs = oldElement.attributes;\n const newAttrs = newElement.attributes;\n\n // compare number of attributes\n if (oldAttrs.length !== newAttrs.length) return false;\n\n // iterate and compare each attribute's name and value\n for (let i = 0; i < oldAttrs.length; i++) {\n const oldAttr = oldAttrs[i];\n const newAttrValue = newElement.getAttribute(oldAttr.name);\n if (oldAttr.value !== newAttrValue) return false;\n }\n }\n\n // handle Text and Comment nodes\n if (\n oldNode.nodeType === 3 /* Node.TEXT_NODE */ ||\n oldNode.nodeType === 8 /* Node.COMMENT_NODE */\n ) {\n if (oldNode.nodeValue !== newNode.nodeValue) return false;\n }\n return true;\n};\n\n/********************************************************\n * 1) Define a \"valid\" child type & utilities\n ********************************************************/\nexport type ValidChild =\n | string\n | number\n | boolean\n | null\n | undefined\n | VNode<VNodeAttributes>;\n\n/**\n * How top-level children are reconciled:\n * - `\"replace\"` (default): full reconciliation — unmentioned nodes are removed.\n * - `\"diff\"`: partial updates — only patch items addressed by `key`/`id` are\n * applied (attributes merge, new items append, unmentioned nodes untouched).\n */\nexport type MorphMode = \"replace\" | \"diff\";\n\nfunction isTextLike(value: unknown): value is string | number | boolean {\n return (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n );\n}\n\nfunction isVNode(value: unknown): value is VNode<VNodeAttributes> {\n return Boolean(\n value &&\n typeof value === \"object\" &&\n \"type\" in (value as Record<string, unknown>),\n );\n}\n\nfunction toValidChild(\n child: VNodeChild,\n // diff mode: a partial patch item may omit `type` (borrowed from the node\n // it addresses) — `{ attributes: ... }` alone is a valid patch object there\n lenient = false,\n): ValidChild | undefined {\n if (child == null) return child; // null or undefined\n if (isTextLike(child)) return child;\n\n if (isVNode(child)) return child;\n\n if (\n lenient &&\n child &&\n typeof child === \"object\" &&\n \"attributes\" in (child as Record<string, unknown>)\n )\n return child as unknown as ValidChild;\n\n // e.g. function or {} -> filter out\n return undefined;\n}\n\n/** fuse consecutive text-like nodes to preserve DOM stability (matches hydrate's behavior) */\nfunction normalizeChildren(\n input: RenderInput,\n lenient = false,\n): Array<ValidChild> {\n const raw: Array<ValidChild> = [];\n\n const pushChild = (child: unknown) => {\n if (Array.isArray(child)) {\n child.forEach(pushChild);\n return;\n }\n\n const valid = toValidChild(child as VNodeChild, lenient);\n if (typeof valid === \"undefined\") return;\n\n // unwrap Fragment-ish nodes (defuss sometimes uses \"fragment\", some code uses \"Fragment\")\n if (\n isVNode(valid) &&\n (valid.type === \"fragment\" || valid.type === \"Fragment\")\n ) {\n const nested = Array.isArray(valid.children) ? valid.children : [];\n nested.forEach(pushChild);\n return;\n }\n\n // ignore booleans/null/undefined as render-nothing\n if (\n valid === null ||\n typeof valid === \"undefined\" ||\n typeof valid === \"boolean\"\n )\n return;\n\n raw.push(valid);\n };\n\n pushChild(input);\n\n // fuse consecutive text nodes into a single string\n const fused: Array<ValidChild> = [];\n let buffer: string | null = null;\n\n const flush = () => {\n if (buffer !== null && buffer.length > 0) fused.push(buffer);\n buffer = null;\n };\n\n for (const child of raw) {\n if (\n typeof child === \"string\" ||\n typeof child === \"number\" ||\n typeof child === \"boolean\"\n ) {\n buffer = (buffer ?? \"\") + String(child);\n continue;\n }\n\n flush();\n fused.push(child);\n }\n\n flush();\n return fused;\n}\n\nfunction getVNodeMatchKey(child: ValidChild): string | null {\n if (!child || typeof child !== \"object\") return null;\n\n const key = child.attributes?.key;\n if (typeof key === \"string\" || typeof key === \"number\")\n return `k:${String(key)}`;\n\n const id = child.attributes?.id;\n if (typeof id === \"string\" && id.length > 0) return `id:${id}`;\n\n return null;\n}\n\n/** human-readable item description for diff-mode error messages */\nfunction describePatchItem(child: ValidChild): string {\n if (child && typeof child === \"object\") {\n return `<${typeof child.type === \"string\" ? child.type : \"component\"}>`;\n }\n return \"plain text\";\n}\n\nfunction getDomMatchKeys(node: Node): Array<string> {\n if (node.nodeType !== 1 /* Node.ELEMENT_NODE */) return [];\n\n const el = node as HTMLElement;\n const keys: Array<string> = [];\n\n // prefer internal key storage, but also accept legacy `key` attribute if present\n const internalKey = (el as HTMLElement & { _defussKey?: string })._defussKey;\n if (internalKey) keys.push(`k:${internalKey}`);\n\n const attrKey = el.getAttribute(\"key\");\n if (attrKey) keys.push(`k:${attrKey}`);\n\n const id = el.id;\n if (id) keys.push(`id:${id}`);\n\n return keys;\n}\n\n/********************************************************\n * 2) Check if a DOM node and a ValidChild match by type\n ********************************************************/\nfunction areNodeAndChildMatching(domNode: Node, child: ValidChild): boolean {\n if (\n typeof child === \"string\" ||\n typeof child === \"number\" ||\n typeof child === \"boolean\"\n ) {\n return domNode.nodeType === 3 /* Node.TEXT_NODE */;\n }\n\n if (isCommentVNode(child)) return domNode.nodeType === 8 /* Node.COMMENT_NODE */;\n\n if (child && typeof child === \"object\") {\n if (domNode.nodeType !== 1 /* Node.ELEMENT_NODE */) return false;\n\n const el = domNode as HTMLElement;\n const oldTag = el.tagName.toLowerCase();\n const newTag =\n typeof child.type === \"string\" ? child.type.toLowerCase() : \"\";\n if (!newTag || oldTag !== newTag) return false;\n\n // Match only by tag name - class changes should be handled by patchElementInPlace\n // This prevents node churn when classes are toggled (e.g., \"danger\" on selection)\n return true;\n }\n\n return false;\n}\n\n/********************************************************\n * 3) Create brand new DOM node(s) from a ValidChild\n ********************************************************/\nfunction createDomFromChild(\n child: ValidChild,\n globals: Globals,\n): Array<Node> | undefined {\n const renderer = getRenderer(globals.window.document);\n\n if (child == null) return undefined;\n\n if (\n typeof child === \"string\" ||\n typeof child === \"number\" ||\n typeof child === \"boolean\"\n ) {\n return [globals.window.document.createTextNode(String(child))];\n }\n\n // create without parent (we'll insert manually and run lifecycle hooks afterwards)\n const created = renderer.createElementOrElements(child) as\n | Node\n | Array<Node>\n | undefined;\n\n if (!created) return undefined;\n const nodes = Array.isArray(created) ? created : [created];\n return nodes.filter(Boolean) as Array<Node>;\n}\n\n/********************************************************\n * 4) Patch an element node in place (attributes + children)\n ********************************************************/\nfunction shouldPreserveFormStateAttribute(\n el: Element,\n attrName: string,\n vnode: VNode<VNodeAttributes>,\n): boolean {\n const tag = el.tagName.toLowerCase();\n const hasExplicit = Object.hasOwn(vnode.attributes ?? {}, attrName);\n\n if (hasExplicit) return false;\n\n // preserve uncontrolled input/textarea/select state unless explicitly controlled by VDOM\n if (tag === \"input\") return attrName === \"value\" || attrName === \"checked\";\n if (tag === \"textarea\") return attrName === \"value\";\n if (tag === \"select\") return attrName === \"value\";\n return false;\n}\n\nfunction patchElementInPlace(\n el: Element,\n vnode: VNode<VNodeAttributes>,\n globals: Globals,\n // diff mode: the vnode is a partial patch — undeclared attributes and\n // delegated handlers are \"not mentioned\", never \"unset\", so removal is skipped\n mergeAttributes = false,\n): void {\n const renderer = getRenderer(globals.window.document);\n\n // remove old attributes not present (but preserve uncontrolled form state)\n const existingAttrs = mergeAttributes ? [] : Array.from(el.attributes);\n const nextAttrs = vnode.attributes ?? {};\n\n for (const attr of existingAttrs) {\n const { name } = attr;\n\n // do not remove internal key if it ever existed as attribute\n if (name === \"key\") continue;\n\n // do not remove event-ish attributes; handlers are delegated elsewhere\n if (name.startsWith(\"on\")) continue;\n\n // treat class/className as equivalent\n if (\n name === \"class\" &&\n (Object.hasOwn(nextAttrs, \"class\") ||\n Object.hasOwn(nextAttrs, \"className\"))\n ) {\n continue;\n }\n\n if (!Object.hasOwn(nextAttrs, name)) {\n if (shouldPreserveFormStateAttribute(el, name, vnode)) continue;\n el.removeAttribute(name);\n }\n }\n\n // Remove stale event handlers: compute registered phase keys - next vnode phase keys\n // This is phase-aware: onClick + onClickCapture → onClickCapture only will correctly\n // remove the bubble handler while keeping the capture handler.\n // Skipped for DOM-derived vnodes (HTML strings / DOM nodes): those cannot declare\n // handlers, so existing delegated handlers are preserved like uncontrolled form state.\n const preserveDelegatedHandlers =\n mergeAttributes ||\n Boolean((nextAttrs as Record<PropertyKey, unknown>)[FROM_DOM_MARKER]);\n\n if (!preserveDelegatedHandlers) {\n const registeredKeys = getRegisteredEventKeys(el as HTMLElement);\n const nextEventKeys = new Set<string>();\n for (const propName of Object.keys(nextAttrs)) {\n const parsed = parseEventPropName(propName);\n if (parsed) {\n const phase = parsed.capture ? \"capture\" : \"bubble\";\n nextEventKeys.add(`${parsed.eventType}:${phase}`);\n }\n }\n for (const key of registeredKeys) {\n if (!nextEventKeys.has(key)) {\n const [eventType, phase] = key.split(\":\");\n removeDelegatedEventByKey(\n el as HTMLElement,\n eventType,\n phase as \"bubble\" | \"capture\",\n );\n }\n }\n }\n\n // set new attributes (includes ref + delegated events via renderer.setAttribute)\n renderer.setAttributes(vnode, el);\n\n // Trigger onMount lifecycle for morphed elements that have a new onMount callback\n // This ensures onMount fires on route changes even when elements are morphed in place\n handleLifecycleEventsForOnMount(el as HTMLElement);\n\n // dangerouslySetInnerHTML => skip child reconciliation\n const d = vnode.attributes?.dangerouslySetInnerHTML;\n if (d && typeof d === \"object\" && typeof d.__html === \"string\") {\n el.innerHTML = d.__html;\n return;\n }\n\n const tag = el.tagName.toLowerCase();\n\n // preserve textarea live value unless explicitly controlled\n if (tag === \"textarea\") {\n const isControlled = Object.hasOwn(nextAttrs, \"value\");\n const isActive = el.ownerDocument?.activeElement === el;\n if (isActive && !isControlled) return;\n }\n\n // diff mode: children are \"not mentioned\" unless explicitly declared, so an\n // attributes-only patch item must not clear the node's existing children.\n // HTML-derived vnodes always carry a (possibly empty) children array —\n // empty means \"undeclared\" there, exactly like absent form attributes.\n // VNode/JSX input keeps the distinction: children: [] clears explicitly.\n if (\n mergeAttributes &&\n (vnode.children === undefined ||\n (vnode.children.length === 0 &&\n (nextAttrs as Record<PropertyKey, unknown>)[FROM_DOM_MARKER]))\n )\n return;\n\n // reconcile children (direct call - bypasses morph guard for internal recursion)\n morphDomDirect(el, (vnode.children ?? []) as RenderInput, globals);\n}\n\n/********************************************************\n * 5) Morph a single DOM node to match a ValidChild\n ********************************************************/\n\n/**\n * Swap `next` in for `old`, clearing the old subtree's handlers first — the\n * same teardown as removal, so delegated handlers and facade listeners\n * (onClearDelegatedEvents hooks) never outlive a replaced element.\n */\nfunction replaceNode(old: Node, next: Node): void {\n if (old.nodeType === 1 /* Node.ELEMENT_NODE */)\n clearDelegatedEventsDeep(old as HTMLElement);\n old.parentNode?.replaceChild(next, old);\n}\nfunction morphNode(\n domNode: Node,\n child: ValidChild,\n globals: Globals,\n mergeAttributes = false,\n): Node | null {\n // text-like\n if (\n typeof child === \"string\" ||\n typeof child === \"number\" ||\n typeof child === \"boolean\"\n ) {\n const text = String(child);\n\n if (domNode.nodeType === 3 /* Node.TEXT_NODE */) {\n if (domNode.nodeValue !== text) domNode.nodeValue = text;\n return domNode;\n }\n\n const next = globals.window.document.createTextNode(text);\n replaceNode(domNode, next);\n return next;\n }\n\n // comment: patch data in place, like text\n if (isCommentVNode(child)) {\n const data = child.value ?? \"\";\n\n if (domNode.nodeType === 8 /* Node.COMMENT_NODE */) {\n if (domNode.nodeValue !== data) domNode.nodeValue = data;\n return domNode;\n }\n\n const next = globals.window.document.createComment(data);\n replaceNode(domNode, next);\n return next;\n }\n\n // element-like (VNode)\n if (child && typeof child === \"object\") {\n const newType = typeof child.type === \"string\" ? child.type : null;\n if (!newType) return domNode;\n\n if (domNode.nodeType !== 1 /* Node.ELEMENT_NODE */) {\n const created = createDomFromChild(child, globals);\n const first = Array.isArray(created) ? created[0] : created;\n if (!first) return null;\n\n domNode.parentNode?.replaceChild(first, domNode);\n handleLifecycleEventsForOnMount(first as HTMLElement);\n return first;\n }\n\n const el = domNode as Element;\n const oldTag = el.tagName.toLowerCase();\n const newTag = newType.toLowerCase();\n\n if (oldTag !== newTag) {\n const created = createDomFromChild(child, globals);\n const first = Array.isArray(created) ? created[0] : created;\n if (!first) return null;\n\n replaceNode(el, first);\n handleLifecycleEventsForOnMount(first as HTMLElement);\n return first;\n }\n\n patchElementInPlace(el, child as VNode<VNodeAttributes>, globals, mergeAttributes);\n return el;\n }\n\n // null/undefined => remove\n if (domNode.nodeType === 1 /* Node.ELEMENT_NODE */)\n clearDelegatedEventsDeep(domNode as HTMLElement);\n domNode.parentNode?.removeChild(domNode);\n return null;\n}\n\n/********************************************************\n * 6) Morph guard - tags DOM subtrees as \"rendering\" to prevent\n * re-entrant / conflicting morphs on the same or ancestor nodes.\n * Unrelated subtrees morph in parallel without blocking.\n ********************************************************/\nconst renderingNodes = new WeakSet<Element>();\nconst pendingMorphs = new Map<\n Element,\n { vdom: RenderInput; globals: Globals; mode: MorphMode }\n>();\n\n/**\n * Resolve the render globals from an element's own document when not given\n * explicitly (isomorphic: browser window, happy-dom window, multi-document).\n */\nexport const resolveGlobals = (el?: Element, globals?: Globals): Globals => {\n if (globals) return globals;\n const win = (el?.ownerDocument?.defaultView ??\n globalThis) as unknown as Globals;\n return { window: win } as unknown as Globals;\n};\n\nfunction isAncestorRendering(el: Element): boolean {\n let current = el.parentElement;\n while (current) {\n if (renderingNodes.has(current)) return true;\n current = current.parentElement;\n }\n return false;\n}\n\nfunction flushPendingMorphs(): void {\n if (pendingMorphs.size === 0) return;\n\n // Snapshot and clear to avoid infinite loops if flush triggers more morphs\n const snapshot = [...pendingMorphs.entries()];\n pendingMorphs.clear();\n\n for (const [el, { vdom, globals, mode }] of snapshot) {\n // Skip if element was detached during parent morph\n if (!el.isConnected) continue;\n // Re-enter through guarded path (handles nested conflicts)\n updateDomWithVdom(el, vdom, globals, mode);\n }\n}\n\n/**\n * Guarded entry point for DOM morphing.\n *\n * If the target element (or an ancestor) is already being morphed,\n * the render is queued (latest-wins) and replayed after the active\n * morph finishes. Morphs on unrelated subtrees proceed immediately\n * without blocking - conflict-free parallel rendering.\n *\n * `globals` is optional: it is derived from `parentElement.ownerDocument`\n * when omitted.\n *\n * `mode` defaults to `\"replace\"` (full reconciliation). Pass `\"diff\"` for\n * partial updates: only `key`/`id`-addressed patch items are applied\n * (attributes merged, new keyed items appended, unmentioned nodes untouched).\n */\nexport function updateDomWithVdom(\n parentElement: Element,\n newVDOM: RenderInput,\n globals?: Globals,\n mode: MorphMode = \"replace\",\n): void {\n const resolvedGlobals = resolveGlobals(parentElement, globals);\n\n // Re-entrant or ancestor conflict → queue latest, return\n if (renderingNodes.has(parentElement) || isAncestorRendering(parentElement)) {\n pendingMorphs.set(parentElement, {\n vdom: newVDOM,\n globals: resolvedGlobals,\n mode,\n });\n return;\n }\n\n renderingNodes.add(parentElement);\n try {\n morphDomDirect(parentElement, newVDOM, resolvedGlobals, mode);\n } finally {\n renderingNodes.delete(parentElement);\n }\n\n // Flush any morphs that were queued during this render\n flushPendingMorphs();\n}\n\n/********************************************************\n * 6b) Diff mode — partial change-sets (patch + append only)\n ********************************************************/\n/**\n * Apply a partial change-set to `targetRoot`: every top-level item must be an\n * element addressed by `key` (preferred) or `id`. Matched nodes are patched in\n * place with attributes *merged* (undeclared attributes, delegated handlers\n * and children stay untouched); unmatched items are appended as new nodes.\n * Nothing else changes: unmentioned siblings keep identity, order and state —\n * diff mode never removes and never moves, so addressing is unambiguous.\n *\n * Why: stream/AI-driven partial updates without resending the whole subtree.\n * Tag changes on an addressed node are applied as an honest in-place\n * replacement (the item fully declares that node).\n */\nfunction morphDiff(\n targetRoot: ParentNode & Node,\n patchItems: Array<ValidChild>,\n globals: Globals,\n): void {\n // first-wins keyed pool of the current children — diff never removes, so\n // duplicate keys can simply share the first node as the address owner\n const keyedPool = new Map<string, Node>();\n for (const node of Array.from(targetRoot.childNodes)) {\n for (const k of getDomMatchKeys(node)) {\n if (!keyedPool.has(k)) keyedPool.set(k, node);\n }\n }\n\n for (const item of patchItems) {\n // formatting whitespace between change-set items (e.g. newlines + indent\n // in a template literal) parses to text nodes but carries no meaning —\n // skip it; only *meaningful* plain text is unaddressable and throws\n if (typeof item === \"string\" && item.trim() === \"\") continue;\n\n // top-level comments in a change-set are annotations with no address:\n // diff never removes or moves, and appending would duplicate them on\n // every repeated patch — skip them (comments *inside* items do morph).\n // VERIFIED: a repeated commented patch leaves no duplicates (morph-comments.test.ts)\n if (isCommentVNode(item)) continue;\n\n // booleans/null are already filtered by normalizeChildren; anything\n // without a key/id (incl. plain text) cannot be addressed unambiguously\n const key = getVNodeMatchKey(item);\n\n if (!key) {\n throw new Error(\n `morph diff: patch items must be elements with a key or id attribute (got ${describePatchItem(item)})`,\n );\n }\n\n const match = keyedPool.get(key);\n\n if (match) {\n // Tag-less patch items are pure patches: borrow the addressed node's\n // tag (only *new* items need one — to create it). An explicitly\n // different tag still replaces the node.\n const patchItem =\n item && typeof item === \"object\" && !(item as VNode).type\n ? { ...item, type: (match as Element).tagName.toLowerCase() }\n : item;\n\n // same tag -> attribute merge (+ declared children); tag change ->\n // in-place replacement by morphNode; mergeAttributes keeps the diff\n // contract (no attribute/handler removal) either way\n morphNode(match, patchItem, globals, true);\n continue;\n }\n\n if (!(item as VNode)?.type) {\n throw new Error(\n `morph diff: new (unmatched) patch items must declare a tag (type), got key/id \"${key}\"`,\n );\n }\n\n // new keyed item -> append (never inserted \"in order\" implicitly: moving\n // or positioning unmentioned siblings would be a guess)\n const created = createDomFromChild(item, globals) ?? [];\n for (const node of created) {\n targetRoot.appendChild(node);\n handleLifecycleEventsForOnMount(node as HTMLElement);\n }\n }\n}\n\ntype MoveParent = ParentNode & Node & { moveBefore?: (node: Node, child: Node | null) => void };\n\n/**\n * Moves `node` (a child of `parent`) before `anchor`. insertBefore() removes the node before inserting it, and the\n * removal blurs a focused element inside it (VERIFIED in Chromium: morph.browser.test.ts). moveBefore() moves\n * atomically and keeps focus, the selection and other live state (iframes, animations), so it is used where the\n * platform has it. Elsewhere, or when it refuses the move, insertBefore() runs and focus and the text selection\n * are put back; state only moveBefore() keeps, such as a playing iframe, restarts there.\n */\nfunction moveNode(parent: MoveParent, node: Node, anchor: Node | null): void {\n if (typeof parent.moveBefore === \"function\") {\n try {\n parent.moveBefore(node, anchor);\n return;\n } catch {\n // VERIFIED: Chromium 156 moves children of connected and detached trees, shadow roots and parsed documents\n // without throwing. HYPOTHESIS: an engine that requires both nodes to be connected throws for detached trees;\n // insertBefore() takes over then\n }\n }\n\n const doc = node.ownerDocument;\n const active = doc?.activeElement as HTMLInputElement | null | undefined;\n const holdsFocus = !!active && active !== doc!.body && node.contains(active);\n // selectionStart throws or is null for inputs without a text selection (checkbox, number, ...)\n let selection: [number, number, \"forward\" | \"backward\" | \"none\"] | undefined;\n if (holdsFocus) {\n try {\n if (active.selectionStart !== null && active.selectionStart !== undefined) {\n selection = [active.selectionStart, active.selectionEnd ?? active.selectionStart, active.selectionDirection ?? \"none\"];\n }\n } catch {\n selection = undefined;\n }\n }\n\n parent.insertBefore(node, anchor);\n\n if (holdsFocus && active.isConnected && doc!.activeElement !== active) {\n active.focus({ preventScroll: true });\n if (selection) active.setSelectionRange(...selection);\n }\n}\n\n/**\n * The common case without the matching machinery: as many children as before, nothing keyed on either side (no\n * `key`, no `id`), and every new child of the kind and tag of the node at its position. The matching below pairs each\n * such child with that node (an unkeyed child takes the first compatible unkeyed node, which is the one at its\n * position), moves nothing, creates nothing and removes nothing, so patching in order is the same morph. Returns\n * false, touching nothing, when the children do not line up.\n * VERIFIED (A/B in Chromium, 2026-11-01): VNode select and swap on 1,000 rows took about a fifth less time; every\n * row's cells line up. morph-reorder.test.ts checks the reused nodes against the matching model for same-length lists.\n * Keyed rows in the same order are left to the full path: VERIFIED (A/B, 2026-11-01): a keyed variant of this check\n * changed no keyed operation beyond run-to-run noise, 500 re-renders of 10 keyed rows included.\n */\nfunction patchByPosition(targetRoot: ParentNode & Node, nextChildren: Array<ValidChild>, globals: Globals): boolean {\n const live = targetRoot.childNodes;\n if (live.length !== nextChildren.length) return false;\n for (let c = 0; c < nextChildren.length; c++) {\n const node = live[c];\n const child = nextChildren[c];\n if (getVNodeMatchKey(child) !== null || !areNodeAndChildMatching(node, child)) return false;\n if (node.nodeType === 1 /* Node.ELEMENT_NODE */ && getDomMatchKeys(node).length > 0) return false;\n }\n // matching nodes are patched in place (same kind and tag), so the live list keeps its order\n for (let c = 0; c < nextChildren.length; c++) morphNode(live[c], nextChildren[c], globals);\n return true;\n}\n\n/********************************************************\n * 7) Raw morph implementation (key/id aware, move-not-replace)\n * Called directly by the guard and by internal recursive\n * child reconciliation (patchElementInPlace).\n ********************************************************/\nfunction morphDomDirect(\n parentElement: Element,\n newVDOM: RenderInput,\n globals: Globals,\n mode: MorphMode = \"replace\",\n): void {\n // Custom elements (hyphenated tags) use light DOM for slotted content.\n // Other elements with shadowRoot should target the shadow root.\n const el = parentElement as HTMLElement;\n const isCustomElement = el.tagName.includes(\"-\");\n // A <template> keeps its children in its content fragment.\n const targetRoot: ParentNode & Node =\n templateContent(parentElement) ??\n (el.shadowRoot && !isCustomElement ? el.shadowRoot : parentElement);\n\n const nextChildren = normalizeChildren(newVDOM, mode === \"diff\");\n\n if (mode === \"diff\") {\n morphDiff(targetRoot, nextChildren, globals);\n return;\n }\n\n if (patchByPosition(targetRoot, nextChildren, globals)) return;\n\n // snapshot existing children once for matching pools; the pools hold their indices\n const existing = Array.from(targetRoot.childNodes);\n\n const keyedPool = new Map<string, number>();\n const nodeKeys: Array<Array<string> | undefined> = [];\n const unkeyedPool: Array<number> = [];\n\n for (let i = 0; i < existing.length; i++) {\n const keys = getDomMatchKeys(existing[i]);\n if (keys.length > 0) {\n nodeKeys[i] = keys;\n let addedToKeyedPool = false;\n for (const k of keys) {\n if (!keyedPool.has(k)) {\n keyedPool.set(k, i);\n addedToKeyedPool = true;\n }\n }\n // all keys duplicates of already-pooled nodes: fall back to the\n // unkeyed pool so the node can still be matched — and, crucially,\n // is removed when left over (duplicate keys must not leak nodes)\n if (!addedToKeyedPool) {\n unkeyedPool.push(i);\n }\n } else {\n unkeyedPool.push(i);\n }\n }\n\n // frees only the keys that address node `i`: a key or id it shares with an earlier node stays with that node, which\n // is otherwise neither matched nor removed (VERIFIED: morph-edge.test.ts, \"removes a node whose id another ...\")\n const consumeKeyedNode = (i: number) => {\n for (const k of nodeKeys[i] ?? []) {\n if (keyedPool.get(k) === i) keyedPool.delete(k);\n }\n };\n\n const takeUnkeyedMatch = (child: ValidChild): number => {\n // try to find a compatible node (preserves focus/state by moving instead of replacing)\n for (let j = 0; j < unkeyedPool.length; j++) {\n const i = unkeyedPool[j];\n if (areNodeAndChildMatching(existing[i], child)) {\n unkeyedPool.splice(j, 1);\n return i;\n }\n }\n\n // SAFE: no match => don't reuse something random, create new node instead\n return -1;\n };\n\n // 1) match every child to an existing node (its index) or none (-1). Matching reads keys and tags only, never\n // positions, so matching first and placing afterwards reuses the same nodes as matching while placing.\n const count = nextChildren.length;\n const matched = new Int32Array(count);\n let inOrder = true;\n let previous = -1;\n for (let c = 0; c < count; c++) {\n const child = nextChildren[c];\n const key = getVNodeMatchKey(child);\n let i = -1;\n if (key) {\n const hit = keyedPool.get(key);\n if (hit !== undefined) {\n i = hit;\n consumeKeyedNode(hit);\n }\n } else {\n i = takeUnkeyedMatch(child);\n }\n matched[c] = i;\n if (i >= 0) {\n if (i < previous) inOrder = false;\n previous = i;\n }\n }\n\n // 2) the matched nodes in the longest run that is already in order stay where they are; only the others move, so\n // swapping two rows moves two and removing one moves none. VERIFIED: the move counts in morph-reorder.test.ts.\n const stays = inOrder ? null : longestIncreasingRun(matched);\n const staying = (c: number) => matched[c] >= 0 && (stays === null || stays[c] === 1);\n\n // 3) left to right, in the order of the markup: patch each node, and put a moved or created one before the next\n // node that stays (or at the end); leftovers between them are removed afterwards\n let anchorAt = 0;\n while (anchorAt < count && !staying(anchorAt)) anchorAt++;\n\n for (let c = 0; c < count; c++) {\n if (anchorAt <= c) {\n anchorAt = c + 1;\n while (anchorAt < count && !staying(anchorAt)) anchorAt++;\n }\n const anchor = anchorAt < count ? existing[matched[anchorAt]] : null;\n const child = nextChildren[c];\n\n if (matched[c] >= 0) {\n const match = existing[matched[c]];\n // move node into place (preserves identity, focus and state)\n if (!staying(c)) moveNode(targetRoot, match, anchor);\n morphNode(match, child, globals);\n continue;\n }\n\n // no match => create and insert\n const created = createDomFromChild(child, globals);\n if (!created || (Array.isArray(created) && created.length === 0)) continue;\n\n const nodes = Array.isArray(created) ? created : [created];\n for (const node of nodes) {\n targetRoot.insertBefore(node, anchor);\n handleLifecycleEventsForOnMount(node as HTMLElement);\n }\n }\n\n // remove remaining unmatched nodes (both keyed leftovers and unkeyed leftovers)\n const remaining = new Set<Node>();\n\n for (const i of unkeyedPool) remaining.add(existing[i]);\n for (const i of keyedPool.values()) remaining.add(existing[i]);\n\n for (const node of remaining) {\n if (node.parentNode === targetRoot) {\n // Clear delegated events before removal to prevent handler leaks\n // (realm-safe element check: works across windows / SSR DOM implementations)\n if (node.nodeType === 1 /* Node.ELEMENT_NODE */) {\n clearDelegatedEventsDeep(node as HTMLElement);\n }\n targetRoot.removeChild(node);\n }\n }\n}\n\n/**\n * Directly blow away all children in `parentElement` and create new DOM\n * from `newVDOM`. This never skips or leaves behind stale nodes,\n * at the cost of losing partial update performance.\n *\n * `globals` is optional: it is derived from `parentElement.ownerDocument`\n * when omitted.\n */\nexport function replaceDomWithVdom(\n parentElement: Element,\n newVDOM: RenderInput,\n globals?: Globals,\n) {\n const resolvedGlobals = resolveGlobals(parentElement, globals);\n\n // 1) Clear all existing DOM children, with the same handler teardown as a\n // morph removal, so onClearDelegatedEvents hooks see every removed element\n while (parentElement.firstChild) {\n const child = parentElement.firstChild;\n if (child.nodeType === 1 /* Node.ELEMENT_NODE */)\n clearDelegatedEventsDeep(child as HTMLElement);\n parentElement.removeChild(child);\n }\n\n // 2) Re-render from scratch\n const renderer = getRenderer(resolvedGlobals.window.document);\n\n const newDom = renderer.createElementOrElements(\n newVDOM as VNode | undefined | Array<VNode | undefined | string>,\n );\n\n // 3) Append the newly created node(s)\n if (Array.isArray(newDom)) {\n for (const node of newDom) {\n if (node) {\n parentElement.appendChild(node);\n handleLifecycleEventsForOnMount(node as HTMLElement);\n }\n }\n } else if (newDom) {\n parentElement.appendChild(newDom);\n handleLifecycleEventsForOnMount(newDom as HTMLElement);\n }\n}\n",
|
|
11
|
+
"export type TransitionType =\n | \"fade\"\n | \"slide-left\"\n | \"slide-right\"\n | \"shake\"\n | \"none\";\n\nexport interface TransitionStyles {\n enter: Record<string, string>;\n enterActive: Record<string, string>;\n exit: Record<string, string>;\n exitActive: Record<string, string>;\n}\n\nexport type TransitionsEasing =\n | \"linear\"\n | \"ease\"\n | \"ease-in\"\n | \"ease-out\"\n | \"ease-in-out\"\n | \"step-start\"\n | \"step-end\";\n\n/** The `transition` option of `morph()`; every field is optional (see {@link DEFAULT_TRANSITION_CONFIG}). */\nexport interface TransitionConfig {\n /** Built-in animation; `\"none\"` keeps `morph()` synchronous. Default `\"fade\"`. */\n type?: TransitionType;\n /** Own style maps for the four phases (not used by `\"fade\"`). */\n styles?: TransitionStyles;\n /** Milliseconds per phase. Default 300. */\n duration?: number;\n /** CSS timing function. Default `\"ease-in-out\"`. */\n easing?: TransitionsEasing | string;\n /** Milliseconds to wait before starting. Default 0. */\n delay?: number;\n /** Animate the morphed element's parent (default) or the element itself. */\n target?: \"parent\" | \"self\";\n}\n\nconst injectShakeKeyframes = (doc: Document | undefined) => {\n if (!doc) return;\n if (!doc.getElementById(\"defuss-shake\")) {\n const style = doc.createElement(\"style\");\n style.id = \"defuss-shake\";\n style.textContent =\n \"@keyframes shake{0%,100%{transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{transform:translate3d(-10px,0,0)}20%,40%,60%,80%{transform:translate3d(10px,0,0)}}\";\n doc.head.appendChild(style);\n }\n};\n\n/** The four phase style maps of a built-in transition type (empty maps for an unknown type). */\nexport const getTransitionStyles = (\n type: TransitionType,\n duration: number,\n easing = \"ease-in-out\",\n): TransitionStyles => {\n const t = `transform ${duration}ms ${easing}, opacity ${duration}ms ${easing}`;\n const styles: Record<string, TransitionStyles> = {\n fade: {\n enter: { opacity: \"0\", transition: t, transform: \"translate3d(0,0,0)\" },\n enterActive: { opacity: \"1\" },\n exit: { opacity: \"1\", transition: t, transform: \"translate3d(0,0,0)\" },\n exitActive: { opacity: \"0\" },\n },\n \"slide-left\": {\n enter: {\n transform: \"translate3d(100%,0,0)\",\n opacity: \"0.5\",\n transition: t,\n },\n enterActive: { transform: \"translate3d(0,0,0)\", opacity: \"1\" },\n exit: { transform: \"translate3d(0,0,0)\", opacity: \"1\", transition: t },\n exitActive: { transform: \"translate3d(-100%,0,0)\", opacity: \"0.5\" },\n },\n \"slide-right\": {\n enter: {\n transform: \"translate3d(-100%,0,0)\",\n opacity: \"0.5\",\n transition: t,\n },\n enterActive: { transform: \"translate3d(0,0,0)\", opacity: \"1\" },\n exit: { transform: \"translate3d(0,0,0)\", opacity: \"1\", transition: t },\n exitActive: { transform: \"translate3d(100%,0,0)\", opacity: \"0.5\" },\n },\n shake: (() => {\n injectShakeKeyframes(\n typeof document !== \"undefined\" ? document : undefined,\n );\n return {\n enter: {\n transform: \"translate3d(0,0,0)\",\n opacity: \"1\",\n transition: \"none\",\n },\n enterActive: {\n transform: \"translate3d(0,0,0)\",\n opacity: \"1\",\n animation: `shake ${duration}ms cubic-bezier(0.36,0.07,0.19,0.97)`,\n },\n exit: {\n transform: \"translate3d(0,0,0)\",\n opacity: \"1\",\n transition: \"none\",\n },\n exitActive: {\n transform: \"translate3d(0,0,0)\",\n opacity: \"1\",\n animation: `shake ${duration}ms cubic-bezier(0.36,0.07,0.19,0.97)`,\n },\n };\n })(),\n };\n return (\n styles[type] || { enter: {}, enterActive: {}, exit: {}, exitActive: {} }\n );\n};\n\n/** Sets each CSS property of `styles` on `el` (`style.setProperty`). */\nexport const applyStyles = (\n el: HTMLElement,\n styles: Record<string, string | number>,\n) =>\n Object.entries(styles).forEach(([k, v]) =>\n el.style.setProperty(k, String(v)),\n );\n\n/** Defaults merged under every transition config. */\nexport const DEFAULT_TRANSITION_CONFIG: TransitionConfig = {\n type: \"fade\",\n duration: 300,\n easing: \"ease-in-out\",\n delay: 0,\n target: \"parent\",\n};\n\nconst wait = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nconst performCrossfade = async (\n element: HTMLElement,\n updateCallback: () => Promise<void>,\n duration: number,\n easing: string,\n): Promise<void> => {\n const originalStyle = element.style.cssText;\n const snapshot = element.cloneNode(true) as HTMLElement;\n // realm-safe: use the element's own document (works across windows / SSR DOMs)\n const doc = element.ownerDocument;\n\n try {\n const rect = element.getBoundingClientRect();\n // the rect is viewport-relative, but the snapshot is positioned in the\n // document (absolute, child of <body>): add the scroll offset, or a\n // scrolled page shows the fading copy scrollY pixels away (VERIFIED: 2154 px\n // off in Chromium before this offset; transitions.browser.test.ts)\n const top = rect.top + (doc.defaultView?.scrollY ?? 0);\n const left = rect.left + (doc.defaultView?.scrollX ?? 0);\n\n // Position snapshot absolutely over original\n snapshot.style.cssText = `position:absolute;top:${top}px;left:${left}px;width:${rect.width}px;height:${rect.height}px;opacity:1;transition:opacity ${duration}ms ${easing};z-index:1000;`;\n\n // Prepare new content (initially hidden)\n element.style.opacity = \"0\";\n element.style.transition = `opacity ${duration}ms ${easing}`;\n\n // Insert snapshot and update content\n doc.body.appendChild(snapshot);\n await updateCallback();\n\n // Trigger simultaneous crossfade\n void element.offsetHeight;\n snapshot.style.opacity = \"0\";\n element.style.opacity = \"1\";\n\n await wait(duration);\n doc.body.removeChild(snapshot);\n } catch (error) {\n if (snapshot.parentElement) doc.body.removeChild(snapshot);\n throw error;\n } finally {\n element.style.cssText = originalStyle;\n }\n};\n\n/**\n * Runs `updateCallback` inside a transition on `element`. `fade` cross-fades a snapshot of the old\n * content over the new one; the other types animate out, run the update, then animate in. Styles\n * the transition set are restored afterwards, also when the update throws (the error propagates).\n */\nexport const performTransition = async (\n element: HTMLElement,\n updateCallback: () => Promise<void>,\n config: TransitionConfig = {},\n): Promise<void> => {\n const {\n type = \"fade\",\n duration = 300,\n easing = \"ease-in-out\",\n delay = 0,\n } = { ...DEFAULT_TRANSITION_CONFIG, ...config };\n\n if (type === \"none\") {\n await updateCallback();\n return;\n }\n\n if (delay > 0) await wait(delay);\n\n // Use crossfade for fade transitions\n if (type === \"fade\") {\n await performCrossfade(element, updateCallback, duration, easing);\n return;\n }\n\n const styles = config.styles || getTransitionStyles(type, duration, easing);\n const originalTransition = element.style.transition;\n const originalAnimation = element.style.animation;\n\n try {\n // Clear any existing animation for shake restart\n if (type === \"shake\") {\n element.style.animation = \"none\";\n void element.offsetHeight;\n }\n\n // Apply exit transition\n applyStyles(element, styles.exit);\n void element.offsetHeight;\n applyStyles(element, styles.exitActive);\n\n await wait(duration);\n\n // Update content\n await updateCallback();\n\n // Apply enter transition\n applyStyles(element, styles.enter);\n void element.offsetHeight;\n applyStyles(element, styles.enterActive);\n\n await wait(duration);\n\n // Restore original styles\n element.style.transition = originalTransition;\n element.style.animation = originalAnimation;\n } catch (error) {\n element.style.transition = originalTransition;\n element.style.animation = originalAnimation;\n throw error;\n }\n};\n",
|
|
12
|
+
"import { type MorphMode, resolveGlobals, updateDomWithVdom } from \"./morph.js\";\nimport { htmlStringToVNodes } from \"./html.js\";\nimport type { RenderInput } from \"./types.js\";\nimport {\n DEFAULT_TRANSITION_CONFIG,\n performTransition,\n type TransitionConfig,\n} from \"./transitions.js\";\n\n/** Options of {@link morph}. */\nexport interface MorphOptions {\n /**\n * Optional transition to apply around the morph.\n * When set (and `type !== \"none\"`), `morph()` returns a `Promise`\n * that resolves once the transition completed.\n */\n transition?: TransitionConfig;\n /**\n * Partial updates: apply only the given change-set instead of reconciling\n * the full child list. Every top-level item must be an element with a\n * `key` (preferred) or `id` — matched nodes are patched with attributes\n * *merged* (undeclared attributes and children stay untouched), unmatched\n * items are appended. Unmentioned siblings keep identity, order and state;\n * diff mode never removes and never moves, so addressing is unambiguous.\n *\n * Plain-text input and key-less items throw (they cannot be addressed).\n *\n * @example\n * ```ts\n * // update one row, append another — everything else is not re-sent:\n * morph(list, `\n * <li key=\"b\">B (updated)</li>\n * <li key=\"c\">C (new)</li>\n * `, { diff: true });\n * ```\n */\n diff?: boolean;\n}\n\n/**\n * In-flight transition content slots. Non-fade transitions apply their morph\n * only after the exit phase (`await wait(duration)` inside performTransition),\n * so a morph issued during that window would be overwritten by stale content.\n * The slot makes such overlaps latest-wins: the deferred update applies\n * whatever content was requested last for the element.\n */\nconst inflightTransitions = new WeakMap<Element, { content: RenderInput }>();\n\n/**\n * Morphs the children of `el` to match the given HTML string or JSX/VNode input.\n *\n * A string is parsed into a DOM tree via the native `DOMParser`\n * of the element's own document (isomorphic: browser, happy-dom, ...);\n * any other `RenderInput` (JSX, VNodes, arrays, text) is used directly.\n * Both paths then morph into the existing DOM using the defuss morph algorithm:\n *\n * - key/id-aware node matching (`key` and `id` attributes)\n * - move-not-replace semantics (preserves node identity, focus, selection\n * and event listeners)\n * - in-place attribute patching for same-tag elements\n * - uncontrolled form-state preservation (live input values survive\n * unless the new HTML explicitly controls them)\n * - shadow DOM / custom element (light DOM) aware\n * - re-entrant morphs on the same or an ancestor element are queued\n * latest-wins and replayed after the active morph finishes\n * - overlapping transitions are latest-wins too: a morph issued while a\n * transition is in flight replaces the content that transition will apply\n *\n * Plain text input morphs as a text node.\n *\n * Unlike an HTML string, a VNode/JSX input can express explicit state\n * (`checked: false`, `value: \"\"`) and carry event handlers.\n *\n * @param el the element whose children (or shadow root) are morphed\n * @param newContent HTML string, JSX/VNode(s) or text describing the next children\n * @param options `transition` animates the swap; `diff` applies a partial change-set\n * @returns `undefined` without a transition (the morph is synchronous); with\n * one, a Promise that resolves once the transition finished\n *\n * @example\n * ```ts\n * import { morph } from \"defuss-morph\";\n *\n * morph(document.getElementById(\"app\")!, \"<ul><li key='a'>Hello</li></ul>\");\n *\n * // JSX / VNodes work too (same API, same algorithm):\n * morph(document.getElementById(\"app\")!, <p>Hi</p>);\n *\n * // with a transition (async):\n * await morph(document.getElementById(\"app\")!, \"<p>Hi</p>\", {\n * transition: { type: \"fade\", duration: 200 },\n * });\n * ```\n */\nexport const morph = (\n el: Element,\n newContent: RenderInput,\n options: MorphOptions = {},\n): void | Promise<void> => {\n const globals = resolveGlobals(el);\n const win = globals.window;\n\n const mode: MorphMode = options.diff ? \"diff\" : \"replace\";\n\n // strings go through the HTML parser; JSX/VNodes are used as-is\n const apply = (content: RenderInput) =>\n updateDomWithVdom(\n el,\n typeof content === \"string\" ? htmlStringToVNodes(content, win.DOMParser) : content,\n globals,\n mode,\n );\n\n const transition = options.transition;\n if (transition && transition.type !== \"none\") {\n const config = { ...DEFAULT_TRANSITION_CONFIG, ...transition };\n const transitionTarget =\n config.target === \"self\" ? (el as HTMLElement) : el.parentElement;\n\n // no transition target (detached root) -> morph directly; still a\n // Promise, as documented, so `morph(...).then()` never hits undefined\n // (VERIFIED: transitions.test.ts awaits it on a detached element)\n if (!transitionTarget) {\n apply(newContent);\n return Promise.resolve();\n }\n\n // register the content slot for this element (replaces any previous one)\n const slot = { content: newContent };\n inflightTransitions.set(el, slot);\n\n return performTransition(\n transitionTarget,\n // apply the latest requested content — but only if this transition\n // still owns the slot; when a newer transition has taken it over (or\n // already completed and cleaned it up), this deferred update is stale\n // and must not clobber the newer content\n async () => {\n if (inflightTransitions.get(el) === slot) apply(slot.content);\n },\n config,\n ).finally(() => {\n // clean up only if no newer transition took over the slot\n if (inflightTransitions.get(el) === slot) inflightTransitions.delete(el);\n });\n }\n\n // plain morph: apply immediately, and if a transition is in flight for this\n // element, rewrite its slot so the deferred update re-applies this (latest)\n // content instead of the transition's stale content\n const slot = inflightTransitions.get(el);\n if (slot) slot.content = newContent;\n\n apply(newContent);\n};\n",
|
|
13
|
+
"import type { DefussKey, RenderInput, VNode, VNodeChild } from \"./types.js\";\n\n/**\n * Why: morph() takes VNodes, and JSX is the readable way to write them, but a JSX compiler needs a runtime to call.\n * Without one here, using `<Reactive>` or a ref meant installing the whole defuss framework for its `jsx()`. This\n * is the smallest runtime that fits morph: it returns plain `{ type, attributes, children }` objects, calls function\n * components at once (there is no component tree to keep, the next render is a new call) and has no state.\n *\n * - automatic runtime: `jsxImportSource: \"defuss-morph\"` (TypeScript, Bun, esbuild, Vite) imports `jsx`, `jsxs` and\n * `Fragment` from `defuss-morph/jsx-runtime` (`jsxDEV` from `defuss-morph/jsx-dev-runtime`);\n * - classic runtime and pages without a build step: `h(type, props, ...children)`.\n *\n * VERIFIED: TypeScript, Bun, esbuild and Vite take `jsxImportSource` from tsconfig.json (probed 2026-11-01; Bun\n * imports `jsx-dev-runtime` by default, so both subpaths exist); scripts/e2e/consumer.tsx type-checks JSX against\n * the packed declarations in every `make e2e`.\n */\n\n/** A function component: called with its props (including `children`, `ref` and `key`), returns what to render. */\nexport type Component<P = any> = (props: P) => RenderInput;\n\ntype Props = { [name: string]: unknown; children?: unknown; key?: DefussKey };\n\n/** Children as a flat list: nested arrays (fragments, `.map()` results) are spliced in place. */\nconst toChildren = (children: unknown): VNodeChild[] =>\n children === undefined ? [] : Array.isArray(children) ? (children.flat(Infinity) as VNodeChild[]) : [children as VNodeChild];\n\nconst isVNode = (value: unknown): value is VNode =>\n typeof value === \"object\" && value !== null && !Array.isArray(value) && \"type\" in value;\n\n/** `<>…</>`: its children, rendered in place of the fragment. */\nexport const Fragment = (props: { children?: unknown }): RenderInput => toChildren(props?.children);\n\n/**\n * The automatic-runtime factory: `jsx(type, props, key)`. A tag name gives a VNode; a function component is called\n * with `props` (children included). A `key` given to a component lands on the element it returns, unless that\n * element has one, so `items.map((item) => <Row key={item.id} item={item} />)` is keyed for morph.\n */\nexport function jsx(type: string | Component, props?: Props | null, key?: DefussKey): RenderInput {\n const { children, ...attributes } = props ?? {};\n const resolvedKey = key ?? attributes.key;\n if (resolvedKey !== undefined) attributes.key = resolvedKey;\n\n if (typeof type === \"function\") {\n const result = type(children === undefined ? attributes : { ...attributes, children });\n // a copy: a component may return the same VNode object for every call\n return resolvedKey !== undefined && isVNode(result) && result.attributes?.key === undefined\n ? { ...result, attributes: { ...result.attributes, key: resolvedKey } }\n : result;\n }\n return { type, attributes, children: toChildren(children) };\n}\n\n/** Same as {@link jsx}; compilers call it for elements with several static children. */\nexport const jsxs = jsx;\n\n/** Same as {@link jsx}; compilers call it in development mode. The extra source arguments are ignored. */\nexport const jsxDEV = (type: string | Component, props?: Props | null, key?: DefussKey): RenderInput => jsx(type, props, key);\n\n/**\n * The classic factory, for `jsxFactory: \"h\"` and for pages without a build step:\n * `h(\"button\", { onClick: save }, \"Save\")` is `<button onClick={save}>Save</button>`.\n */\nexport function h(type: string | Component, props?: Props | null, ...children: unknown[]): RenderInput {\n return jsx(type, children.length === 0 ? props : { ...props, children: children.length === 1 ? children[0] : children });\n}\n\n/**\n * JSX types for `jsxImportSource: \"defuss-morph\"`. Loose on purpose: any tag, any attribute. A JSX expression is a\n * `RenderInput` (a fragment is an array), and a component may return anything morph renders.\n */\nexport declare namespace JSX {\n type Element = RenderInput;\n type ElementType = string | Component;\n interface ElementChildrenAttribute {\n children: {};\n }\n interface IntrinsicAttributes {\n key?: DefussKey;\n }\n interface IntrinsicElements {\n [tagName: string]: { [attribute: string]: any };\n }\n}\n",
|
|
14
|
+
"import type { RefLike } from \"./types.js\";\n\n/**\n * Why a plain object and not defuss's store-backed Ref: morph only ever assigns `current`, and the forwardRef\n * pattern needs one free slot for a component's API, so `{ current, state }` is all a ref has to be; defuss's richer\n * Ref stays assignable to it (RefLike). VERIFIED: src/reactive.test.ts keeps `current` on the same node across\n * morphs and drives a component through `ref.state`.\n *\n * A reference to a rendered element. morph sets `current` when it creates or patches the element that carries\n * `ref={...}`; a morph that keeps the element keeps `current` pointing at the same node. `state` is free for the\n * component that owns the element: the forwardRef pattern puts the component's API there, for its parent to call.\n */\nexport interface Ref<T extends Element = HTMLElement, S = unknown> extends RefLike {\n current: T | null;\n state?: S;\n}\n\n/**\n * Creates an empty {@link Ref}. `current` stays `null` until morph renders the element that carries it, so read it\n * in an event handler, in `onMount` or after the morph call, not in the component body.\n */\nexport const createRef = <T extends Element = HTMLElement, S = unknown>(state?: S): Ref<T, S> => ({\n current: null,\n state,\n});\n\n/** True for objects with a `current` property, the shape morph assigns refs to. */\nexport const isRef = (value: unknown): value is RefLike =>\n typeof value === \"object\" && value !== null && \"current\" in value;\n",
|
|
15
|
+
"import { morph } from \"./api.js\";\nimport { htmlStringToVNodes } from \"./html.js\";\nimport { isRef } from \"./ref.js\";\nimport type { RefLike, RenderInput, VNode, VNodeChild } from \"./types.js\";\n\n/**\n * Why: re-rendering a region whenever a store changes is the loop most pages need, and morph makes the naive\n * version correct: render the whole region again and morph it in, and every node that stays keeps its focus, typed\n * input and listeners. Three entry points share one core, as in defuss: `reactive()` for a known element or ref,\n * `<Reactive />` for a JSX tree, and defuss-query's `df$(selector).reactive()` for markup already in the page.\n */\n\n/**\n * What `reactive()` subscribes to: a defuss-store store (`createStore()`, `computed()`), or anything whose\n * `subscribe(listener)` returns an unsubscribe function or an object with `unsubscribe()`.\n */\nexport interface Subscribable {\n subscribe(listener: (...args: any[]) => unknown): unknown;\n}\n\n/** Configuration of {@link reactive} and {@link Reactive}. */\nexport interface ReactiveConfig {\n /** One store, or several: a change in any of them re-renders. */\n store: Subscribable | readonly Subscribable[];\n /** Returns the region's next content: JSX/VNodes or an HTML string. Keep it pure; it may run more often than the stores change. */\n render: () => RenderInput;\n /** Runs once, when the region is disposed (the returned function, `signal` or the `<Reactive>` element's unmount). */\n cleanup?: () => void;\n /** Disposes the region when aborted: the way to end a `df$(...).reactive()` binding, which returns the selection. */\n signal?: AbortSignal;\n}\n\n/** Where {@link reactive} renders: an element, a ref to one, or a list of elements (a defuss-query selection, a NodeList). */\nexport type ReactiveTarget = Element | RefLike | ArrayLike<Element>;\n\nconst isElement = (value: unknown): value is Element =>\n typeof value === \"object\" && value !== null && (value as Node).nodeType === 1;\n\n/** The stores as a list, each checked before any subscription starts, so a bad entry leaks nothing. */\nconst toStores = (store: ReactiveConfig[\"store\"] | undefined, caller: string): readonly Subscribable[] => {\n const stores = Array.isArray(store) ? store : [store];\n stores.forEach((candidate, index) => {\n if (typeof (candidate as Subscribable | undefined)?.subscribe !== \"function\") {\n throw new TypeError(`${caller}: store${Array.isArray(store) ? ` ${index}` : \"\"} has no subscribe() method`);\n }\n });\n return stores as readonly Subscribable[];\n};\n\n/** Subscribes `update` to every store; the result unsubscribes from all of them. */\nconst listen = (stores: readonly Subscribable[], update: () => void): (() => void) => {\n const unsubscribes = stores.map((store) => {\n const result = store.subscribe(() => update());\n if (typeof result === \"function\") return result as () => unknown;\n return () => (result as { unsubscribe?: () => unknown } | undefined)?.unsubscribe?.();\n });\n return () => {\n for (const unsubscribe of unsubscribes) unsubscribe();\n };\n};\n\n/** The elements a target names at render time: a ref is read on every render, a list is a snapshot. */\nconst resolveTarget = (target: ReactiveTarget): (() => Element[]) => {\n if (isElement(target)) return () => [target];\n if (isRef(target)) {\n if (!isElement(target.current)) {\n throw new TypeError(\n \"reactive: the ref has no element yet; call reactive() after the element is rendered (in onMount or later)\",\n );\n }\n return () => (isElement(target.current) ? [target.current] : []);\n }\n if (target && typeof (target as ArrayLike<Element>).length === \"number\") {\n const elements = Array.from(target as ArrayLike<Element>).filter(isElement);\n return () => elements;\n }\n throw new TypeError(\"reactive: the target must be an element, a ref or a list of elements\");\n};\n\n/**\n * Renders `config.render()` into `target` now, then again whenever a store changes, by morphing it in: nodes that\n * stay keep their identity, focus, typed input and listeners. The first render runs before the subscriptions start.\n * Returns the dispose function: it unsubscribes from every store and runs `config.cleanup` once.\n *\n * @example\n * ```ts\n * import { reactive } from \"defuss-morph\";\n * import { createStore } from \"defuss-store\";\n *\n * const cart = createStore({ count: 0 });\n * const dispose = reactive({ store: cart, render: () => `<p>${cart.value.count} items</p>` }, cartEl);\n * cart.set(\"count\", 2); // <p>2 items</p>, the same <p> as before\n * ```\n */\nexport function reactive(config: ReactiveConfig, target: ReactiveTarget): () => void {\n const stores = toStores(config?.store, \"reactive\");\n if (typeof config.render !== \"function\") throw new TypeError(\"reactive: config.render must be a function\");\n const elements = resolveTarget(target);\n if (config.signal?.aborted || elements().length === 0) return () => {};\n\n // one render per element: VNodes carry refs and handlers, which must not be shared between two elements\n const update = () => {\n for (const el of elements()) morph(el, config.render());\n };\n update();\n\n const unsubscribe = listen(stores, update);\n let disposed = false;\n const dispose = () => {\n if (disposed) return;\n disposed = true;\n unsubscribe();\n config.signal?.removeEventListener(\"abort\", dispose);\n config.cleanup?.();\n };\n config.signal?.addEventListener(\"abort\", dispose, { once: true });\n return dispose;\n}\n\n/** Props of {@link Reactive}: the {@link ReactiveConfig}, the wrapper's tag and any attribute for the wrapper. */\nexport interface ReactiveProps extends Omit<ReactiveConfig, \"signal\"> {\n /** The wrapper element's tag. Default: `\"div\"`. */\n tag?: string;\n /** Set to the wrapper element. */\n ref?: RefLike;\n [attribute: string]: unknown;\n}\n\n/** The live subscription of each mounted `<Reactive>` wrapper, with the cleanup of its latest render. */\nconst mounted = new WeakMap<Element, { unsubscribe: () => void; cleanup?: () => void }>();\n\n/**\n * A render result as wrapper children; an HTML string is parsed like morph() parses it. Text without `<` or `&`\n * parses to itself, so it needs no parser: `render={() => String(count)}` also works on a server without a global\n * DOMParser (VERIFIED: the packed-tarball consumer in Node threw there before).\n */\nconst toChildren = (content: RenderInput): VNodeChild[] => {\n if (typeof content === \"string\") {\n if (!/[<&]/.test(content)) return content === \"\" ? [] : [content];\n const Parser = (globalThis as { DOMParser?: typeof DOMParser }).DOMParser;\n if (!Parser) {\n throw new TypeError(\"Reactive: rendering an HTML string needs a global DOMParser; return JSX/VNodes, or call reactive()\");\n }\n return htmlStringToVNodes(content, Parser);\n }\n return Array.isArray(content) ? ((content as unknown[]).flat(Infinity) as VNodeChild[]) : [content as VNodeChild];\n};\n\n/**\n * A JSX component that re-renders its content whenever a store changes. It renders a wrapper element (`tag`,\n * default `div`) whose children are `render()`; other props go to the wrapper. The subscription starts when the\n * wrapper is mounted and ends when it leaves the document, which also runs `cleanup`. A parent re-render passes the\n * latest `render` and `store`, and the children it produces are morphed in like any other render.\n *\n * @example\n * ```tsx\n * import { Reactive } from \"defuss-morph\";\n * import { createStore } from \"defuss-store\";\n *\n * const counter = createStore({ count: 0 });\n *\n * <Reactive tag=\"section\" store={counter} render={() => (\n * <button onClick={() => counter.set(\"count\", counter.value.count + 1)}>{counter.value.count}</button>\n * )} />\n * ```\n */\nexport function Reactive(props: ReactiveProps): VNode {\n const { store, render, cleanup, tag = \"div\", onMount, onUnmount, children: _children, ...attributes } = props;\n const stores = toStores(store, \"Reactive\");\n if (typeof render !== \"function\") throw new TypeError(\"Reactive: the render prop must be a function\");\n\n return {\n type: tag,\n attributes: {\n ...attributes,\n // morph runs onMount in a microtask after inserting the wrapper, and again after every patch of it by a\n // parent re-render: the subscription moves to this render's stores and render function, and one render here\n // picks up a store change made between the render that built the wrapper and this callback. VERIFIED:\n // reactive.test.ts (\"picks up a store change made before its mount callback ran\", \"keeps one subscription\")\n onMount: (el: Element) => {\n mounted.get(el)?.unsubscribe();\n mounted.set(el, { unsubscribe: listen(stores, () => morph(el, render())), cleanup });\n morph(el, render());\n if (typeof onMount === \"function\") onMount(el);\n },\n onUnmount: (el: Element) => {\n const entry = mounted.get(el);\n mounted.delete(el);\n entry?.unsubscribe();\n entry?.cleanup?.();\n if (typeof onUnmount === \"function\") onUnmount(el);\n },\n },\n children: toChildren(render()),\n };\n}\n\n/** The `.reactive()` method {@link installReactive} adds to every defuss-query selection. */\nexport interface ReactiveQueryMethod {\n /** Calls {@link reactive} with this selection as the target and returns the selection; end it with `config.signal`. */\n reactive(config: ReactiveConfig): this;\n}\n\n/**\n * Adds `.reactive(config)` to defuss-query's selections (`df$.fn`, the shared prototype), so markup already in the\n * page becomes reactive by selector: `df$(\"#cart\").reactive({ store, render })`. Idempotent; returns `df$`. The CDN\n * bundle calls it itself when it loads after defuss-query; with defuss-morph loaded first, call\n * `df$.installReactive(df$)` once defuss-query has loaded.\n */\n// Why a property on df$.fn and not a wrapper around df$: every selection defuss-query creates inherits from df$.fn,\n// so selections from df$(), .find() and .children() all get the method, and df$ itself stays defuss-query's object.\n// VERIFIED: reactive.test.ts installs it on createDf$(morph) from defuss-query/core.\nexport const installReactive = <Q>(df$: Q): Q => {\n const fn = (df$ as { fn?: unknown } | null | undefined)?.fn;\n if (typeof fn !== \"object\" || fn === null) {\n throw new TypeError(\"installReactive: expected defuss-query's df$ (a df$ with a df$.fn prototype)\");\n }\n Object.defineProperty(fn, \"reactive\", {\n configurable: true,\n writable: true,\n value: function (this: ArrayLike<Element>, config: ReactiveConfig) {\n reactive(config, this);\n return this;\n },\n });\n return df$;\n};\n",
|
|
16
|
+
"import * as api from \"./index.js\";\n\n/**\n * Why: the CDN bundle (dist/all.js / all.min.js) is also loaded via a plain\n * <script type=\"module\" src=\"...\"> tag — no ESM import statement, so the\n * module's exports are unreachable for the page. Evaluating the bundle\n * therefore declares a `df$` global and exposes the full public API on it:\n *\n * <script type=\"module\" src=\"https://cdn.jsdelivr.net/npm/defuss-morph@latest/dist/all.min.js\"></script>\n * <script type=\"module\">\n * window.df$.morph(document.getElementById(\"app\"), \"<p>Hi</p>\");\n * window.df$.updateDomWithVdom(app, [{ type: \"input\", attributes: { checked: false }, children: [] }], { window });\n * </script>\n *\n * A pre-existing `df$` object or function is preserved (the API is assigned\n * onto it); any other value (or none) is replaced with a fresh object. This\n * keeps script order robust: loading morph after a script that declared `df$`\n * as a function (e.g. dequery) does not clobber it.\n */\ndeclare global {\n var df$: typeof api | undefined;\n\n interface Window {\n df$: typeof api | undefined;\n }\n}\n\nif (typeof globalThis !== \"undefined\") {\n const g = globalThis as { df$: unknown };\n const current = g.df$;\n if (\n current === null ||\n (typeof current !== \"object\" && typeof current !== \"function\")\n ) {\n g.df$ = {};\n }\n Object.assign(g.df$ as Record<string, unknown>, api);\n // loaded after defuss-query (or defuss-shadcn, which embeds it): its selections get .reactive() at once. In the\n // other order df$.fn does not exist yet and the page calls df$.installReactive(df$) (VERIFIED: both orders in\n // global.browser.test.ts, with defuss-query's real CDN bundle)\n const fn = (g.df$ as { fn?: unknown }).fn;\n if (typeof fn === \"object\" && fn !== null) api.installReactive(g.df$);\n}\n"
|
|
13
17
|
],
|
|
14
|
-
"mappings": "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",
|
|
15
|
-
"debugId": "
|
|
18
|
+
"mappings": "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",
|
|
19
|
+
"debugId": "18D1BB0152DB217664756E2164756E21",
|
|
16
20
|
"names": []
|
|
17
21
|
}
|