@dom-expressions/runtime 0.50.0-next.15

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.
@@ -0,0 +1 @@
1
+ export default function reconcileArrays(parentNode: Node, a: Node[], b: Node[]): void;
@@ -0,0 +1,149 @@
1
+ // Slightly modified version of: https://github.com/WebReflection/udomdiff/blob/master/index.js
2
+ import { $$SLOT } from "./constants";
3
+
4
+ export default function reconcileArrays(parentNode, a, b, marker) {
5
+ let bLength = b.length,
6
+ aEnd = a.length,
7
+ bEnd = bLength,
8
+ aStart = 0,
9
+ bStart = 0,
10
+ tail = a[aEnd - 1],
11
+ tailTag = tail[$$SLOT],
12
+ // Ownership tag: an unclaimed node (no `$$SLOT`) is fair game; a tagged
13
+ // node belongs only to the slot whose marker matches. If `a`'s tail has
14
+ // migrated to another slot — same parent or otherwise — `tail.nextSibling`
15
+ // points into a region we don't own, so fall back to `marker`. `marker ||
16
+ // null` keeps non-multi (root-mode) callers happy.
17
+ after =
18
+ tail.parentNode === parentNode && (!tailTag || tailTag === marker)
19
+ ? tail.nextSibling
20
+ : marker || null,
21
+ map = null,
22
+ anchor,
23
+ anchorTag;
24
+
25
+ while (aStart < aEnd || bStart < bEnd) {
26
+ // common prefix
27
+ if (a[aStart] === b[bStart]) {
28
+ aStart++;
29
+ bStart++;
30
+ continue;
31
+ }
32
+ // common suffix
33
+ while (a[aEnd - 1] === b[bEnd - 1]) {
34
+ aEnd--;
35
+ bEnd--;
36
+ }
37
+ // append
38
+ if (aEnd === aStart) {
39
+ let node;
40
+ if (bEnd < bLength) {
41
+ if (bStart) {
42
+ const prev = b[bStart - 1];
43
+ const prevTag = prev[$$SLOT];
44
+ node =
45
+ prev.parentNode === parentNode && (!prevTag || prevTag === marker)
46
+ ? prev.nextSibling
47
+ : after;
48
+ } else node = b[bEnd - bStart];
49
+ } else node = after;
50
+
51
+ while (bStart < bEnd) {
52
+ const n = b[bStart++];
53
+ parentNode.insertBefore(n, node);
54
+ if (marker) n[$$SLOT] = marker;
55
+ }
56
+ // remove
57
+ } else if (bEnd === bStart) {
58
+ while (aStart < aEnd) {
59
+ const n = a[aStart++];
60
+ if (!map || !map.has(n)) {
61
+ const tag = n[$$SLOT];
62
+ if (n.parentNode === parentNode && (!tag || tag === marker)) n.remove();
63
+ }
64
+ }
65
+ // swap backward — symmetric end-swap detected. Walk inward with a single
66
+ // stable front anchor (a[aStart]); each move targets the same DOM-position
67
+ // so the browser's adjacency cache stays warm and per-call native
68
+ // `insertBefore` cost drops sharply on reorder-heavy patterns (e.g. reverse).
69
+ // Only optimize when the anchor still belongs to us; otherwise fall through
70
+ // to the map branch which gates each destructive op. The anchor and its
71
+ // tag are read once per detected swap and reused — important on hot
72
+ // reorder benches (`reconcile-permute reverse`) where this branch fires
73
+ // on every inner-loop step.
74
+ } else if (
75
+ (anchor = a[aStart]) === b[bEnd - 1] &&
76
+ b[bStart] === a[aEnd - 1] &&
77
+ anchor.parentNode === parentNode &&
78
+ (!(anchorTag = anchor[$$SLOT]) || anchorTag === marker)
79
+ ) {
80
+ // Tightest inner loop in the file; one `insertBefore` per iter plus an
81
+ // end-condition probe. Splitting on `marker` avoids a per-iter branch in
82
+ // the hot path — js-framework-benchmark `05_swap1k` regresses ~6.5% when
83
+ // this is collapsed (validated 2026-05-16 on Chrome headless).
84
+ if (marker) {
85
+ do {
86
+ const n = a[--aEnd];
87
+ parentNode.insertBefore(n, anchor);
88
+ n[$$SLOT] = marker;
89
+ bStart++;
90
+ if (aStart >= aEnd - 1 || bStart >= bEnd) break;
91
+ } while (a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1]);
92
+ } else {
93
+ do {
94
+ parentNode.insertBefore(a[--aEnd], anchor);
95
+ bStart++;
96
+ if (aStart >= aEnd - 1 || bStart >= bEnd) break;
97
+ } while (a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1]);
98
+ }
99
+ // fallback to map
100
+ } else {
101
+ if (!map) {
102
+ map = new Map();
103
+ let i = bStart;
104
+
105
+ while (i < bEnd) map.set(b[i], i++);
106
+ }
107
+
108
+ const index = map.get(a[aStart]);
109
+ if (index != null) {
110
+ if (bStart < index && index < bEnd) {
111
+ let i = aStart,
112
+ sequence = 1,
113
+ t;
114
+
115
+ while (++i < aEnd && i < bEnd) {
116
+ if ((t = map.get(a[i])) == null || t !== index + sequence) break;
117
+ sequence++;
118
+ }
119
+
120
+ if (sequence > index - bStart) {
121
+ const head = a[aStart];
122
+ const headTag = head[$$SLOT];
123
+ const node =
124
+ head.parentNode === parentNode && (!headTag || headTag === marker) ? head : after;
125
+ while (bStart < index) {
126
+ const n = b[bStart++];
127
+ parentNode.insertBefore(n, node);
128
+ if (marker) n[$$SLOT] = marker;
129
+ }
130
+ } else {
131
+ const oldNode = a[aStart++];
132
+ const newNode = b[bStart++];
133
+ const oldTag = oldNode[$$SLOT];
134
+ if (oldNode.parentNode === parentNode && (!oldTag || oldTag === marker)) {
135
+ parentNode.replaceChild(newNode, oldNode);
136
+ } else {
137
+ parentNode.insertBefore(newNode, after);
138
+ }
139
+ if (marker) newNode[$$SLOT] = marker;
140
+ }
141
+ } else aStart++;
142
+ } else {
143
+ const n = a[aStart++];
144
+ const nTag = n[$$SLOT];
145
+ if (n.parentNode === parentNode && (!nTag || nTag === marker)) n.remove();
146
+ }
147
+ }
148
+ }
149
+ }
@@ -0,0 +1,3 @@
1
+ import { Serializer } from "seroval";
2
+
3
+ export default function createSerializer(onData: (value: string) => void): Serializer;
@@ -0,0 +1,54 @@
1
+ import { Feature, Serializer, getCrossReferenceHeader } from "seroval";
2
+ import {
3
+ AbortSignalPlugin,
4
+ CustomEventPlugin,
5
+ DOMExceptionPlugin,
6
+ EventPlugin,
7
+ FormDataPlugin,
8
+ HeadersPlugin,
9
+ ReadableStreamPlugin,
10
+ RequestPlugin,
11
+ ResponsePlugin,
12
+ URLPlugin,
13
+ URLSearchParamsPlugin
14
+ } from "seroval-plugins/web";
15
+
16
+ const ES2017FLAG =
17
+ Feature.AggregateError | // ES2021
18
+ Feature.BigIntTypedArray; // ES2020;
19
+
20
+ const GLOBAL_IDENTIFIER = "_$HY.r"; // TODO this is a pending name
21
+
22
+ export function createSerializer({ onData, onDone, scopeId, onError, plugins: customPlugins }) {
23
+ const defaultPlugins = [
24
+ AbortSignalPlugin,
25
+ // BlobPlugin,
26
+ CustomEventPlugin,
27
+ DOMExceptionPlugin,
28
+ EventPlugin,
29
+ // FilePlugin,
30
+ FormDataPlugin,
31
+ HeadersPlugin,
32
+ ReadableStreamPlugin,
33
+ RequestPlugin,
34
+ ResponsePlugin,
35
+ URLSearchParamsPlugin,
36
+ URLPlugin
37
+ ];
38
+
39
+ const allPlugins = customPlugins ? [...customPlugins, ...defaultPlugins] : defaultPlugins;
40
+
41
+ return new Serializer({
42
+ scopeId,
43
+ plugins: allPlugins,
44
+ globalIdentifier: GLOBAL_IDENTIFIER,
45
+ disabledFeatures: ES2017FLAG,
46
+ onData,
47
+ onDone,
48
+ onError
49
+ });
50
+ }
51
+
52
+ export function getLocalHeaderScript(id) {
53
+ return getCrossReferenceHeader(id) + ";";
54
+ }
@@ -0,0 +1,193 @@
1
+ import { JSX } from "./jsx.js";
2
+ export const DOMWithState: Record<string, Record<string, 1 | 2>>;
3
+ export const ChildProperties: Set<string>;
4
+ export const DelegatedEvents: Set<string>;
5
+ export const DOMElements: Set<string>;
6
+ export const SVGElements: Set<string>;
7
+ export const MathMLElements: Set<string>;
8
+ export const VoidElements: Set<string>;
9
+ export const RawTextElements: Set<string>;
10
+ export const Namespaces: Record<string, string>;
11
+
12
+ type MountableElement = Element | Document | ShadowRoot | DocumentFragment | Node;
13
+
14
+ export function renderToString<T>(
15
+ fn: () => T,
16
+ options?: {
17
+ nonce?: string;
18
+ renderId?: string;
19
+ noScripts?: boolean;
20
+ plugins?: any[];
21
+ manifest?: Record<
22
+ string,
23
+ { file: string; css?: string[]; isEntry?: boolean; imports?: string[] }
24
+ > & { _base?: string };
25
+ onError?: (err: any) => void;
26
+ }
27
+ ): string;
28
+ /** @deprecated use renderToStream which also returns a promise */
29
+ export function renderToStringAsync<T>(
30
+ fn: () => T,
31
+ options?: {
32
+ timeoutMs?: number;
33
+ nonce?: string;
34
+ renderId?: string;
35
+ noScripts?: boolean;
36
+ plugins?: any[];
37
+ manifest?: Record<
38
+ string,
39
+ { file: string; css?: string[]; isEntry?: boolean; imports?: string[] }
40
+ > & { _base?: string };
41
+ onError?: (err: any) => void;
42
+ }
43
+ ): Promise<string>;
44
+ export function renderToStream<T>(
45
+ fn: () => T,
46
+ options?: {
47
+ nonce?: string;
48
+ renderId?: string;
49
+ noScripts?: boolean;
50
+ plugins?: any[];
51
+ manifest?: Record<
52
+ string,
53
+ { file: string; css?: string[]; isEntry?: boolean; imports?: string[] }
54
+ > & { _base?: string };
55
+ onCompleteShell?: (info: { write: (v: string) => void }) => void;
56
+ onCompleteAll?: (info: { write: (v: string) => void }) => void;
57
+ onError?: (err: any) => void;
58
+ }
59
+ ): {
60
+ then: (fn: (html: string) => void) => void;
61
+ pipe: (writable: { write: (v: string) => void; end: () => void }) => void;
62
+ pipeTo: (writable: WritableStream) => Promise<void>;
63
+ };
64
+
65
+ export function HydrationScript(props: { nonce?: string; eventNames?: string[] }): JSX.Element;
66
+ export function ssr(template: string[] | string, ...nodes: any[]): { t: string };
67
+ export function ssrElement(
68
+ name: string,
69
+ props: any,
70
+ children: any,
71
+ needsId: boolean
72
+ ): { t: string };
73
+ export function ssrClassName(value: string | { [k: string]: boolean } | Array<any>): string;
74
+ export function ssrStyle(value: string | { [k: string]: string }): string;
75
+ export function ssrStyleProperty(name: string, value: any): string;
76
+ export function ssrAttribute(key: string, value: any): string;
77
+ export function ssrGroup<T extends () => any[]>(fn: T, n: number): T;
78
+ export function ssrHydrationKey(): string;
79
+ export function resolveSSRNode(node: any, result?: any, top?: boolean): any;
80
+ export function escape(s: any, attr?: boolean): any;
81
+ export function applyRef(
82
+ r: ((element: any) => void) | ((element: any) => void)[],
83
+ element: any
84
+ ): void;
85
+ export function useAssets(fn: () => JSX.Element): void;
86
+ export function getAssets(): string;
87
+ export function getHydrationKey(): string | undefined;
88
+ export function effect<T>(fn: (prev?: T) => T, effect: (value: T, prev?: T) => void): void;
89
+ export function memo<T>(fn: () => T, equal: boolean): () => T;
90
+ export function createComponent<T>(Comp: (props: T) => JSX.Element, props: T): JSX.Element;
91
+ export function mergeProps(...sources: unknown[]): unknown;
92
+ export function getOwner(): unknown;
93
+ export function generateHydrationScript(options?: {
94
+ nonce?: string;
95
+ eventNames?: string[];
96
+ }): string;
97
+ export declare const RequestContext: unique symbol;
98
+ export interface RequestEvent {
99
+ request: Request;
100
+ locals: Record<string | number | symbol, any>;
101
+ }
102
+ export function getRequestEvent(): RequestEvent | undefined;
103
+
104
+ export function Assets(props: { children?: JSX.Element }): JSX.Element;
105
+ export function untrack<T>(fn: () => T): T;
106
+
107
+ // client-only APIs
108
+
109
+ /** @deprecated not supported on the server side */
110
+ export function style(
111
+ node: Element,
112
+ value: { [k: string]: string },
113
+ prev?: { [k: string]: string }
114
+ ): void;
115
+
116
+ /** @deprecated not supported on the server side */
117
+ export function insert<T>(
118
+ parent: MountableElement,
119
+ accessor: (() => T) | T,
120
+ marker?: Node | null,
121
+ init?: JSX.Element
122
+ ): JSX.Element;
123
+
124
+ /** @deprecated not supported on the server side */
125
+ export function spread<T>(node: Element, accessor: T, skipChildren?: Boolean): void;
126
+
127
+ /** @deprecated not supported on the server side */
128
+ export function delegateEvents(eventNames: string[]): void;
129
+ /** @deprecated not supported on the server side */
130
+ export function registerDelegatedRoot(root: MountableElement): void;
131
+ /** @deprecated not supported on the server side */
132
+ export function unregisterDelegatedRoot(root: MountableElement): void;
133
+ /** @deprecated not supported on the server side */
134
+ export function registerDelegatedContainer(
135
+ container: MountableElement,
136
+ owner?: MountableElement
137
+ ): void;
138
+ /** @deprecated not supported on the server side */
139
+ export function unregisterDelegatedContainer(
140
+ container: MountableElement,
141
+ owner?: MountableElement
142
+ ): void;
143
+ /** @deprecated not supported on the server side */
144
+ export function getDelegatedRoot(node: MountableElement): MountableElement | undefined;
145
+ /** @deprecated not supported on the server side */
146
+ export function dynamicProperty(props: unknown, key: string): unknown;
147
+ /** @deprecated not supported on the server side */
148
+ export function setAttribute(node: Element, name: string, value: string): void;
149
+ /** @deprecated not supported on the server side */
150
+ export function setAttributeNS(node: Element, namespace: string, name: string, value: string): void;
151
+
152
+ /** @deprecated not supported on the server side */
153
+ export function addEvent(node: Element, name: string, handler: () => void, delegate: boolean): void;
154
+
155
+ /** @deprecated not supported on the server side */
156
+ export function render(code: () => JSX.Element, element: MountableElement): () => void;
157
+ /**
158
+ * @deprecated not supported on the server side
159
+ * @param flag
160
+ * - `undefined` — clone the template as-is (uses `cloneNode`).
161
+ * - `1` — use `document.importNode` instead of `cloneNode`.
162
+ * - `2` — the template html is wrapped; the outer tag is stripped at clone time.
163
+ */
164
+ export function template(html: string, flag?: 1 | 2): () => Element;
165
+ /** @deprecated not supported on the server side */
166
+ export function setProperty(node: Element, name: string, value: any): void;
167
+ /** @deprecated not supported on the server side */
168
+ export function className(node: Element, value: string): void;
169
+ /** @deprecated not supported on the server side */
170
+ export function assign(node: Element, props: any, skipChildren?: Boolean): void;
171
+
172
+ /** @deprecated not supported on the server side */
173
+ export function hydrate(
174
+ fn: () => JSX.Element,
175
+ node: MountableElement,
176
+ options?: { renderId?: string; owner?: unknown }
177
+ ): () => void;
178
+
179
+ /** @deprecated not supported on the server side */
180
+ export function getNextElement(template?: () => Element): Element;
181
+ /** @deprecated not supported on the server side */
182
+ export function getNextMatch(start: Node, elementName: string): Element;
183
+ /** @deprecated not supported on the server side */
184
+ export function getNextMarker(start: Node): [Node, Array<Node>];
185
+ /** @deprecated not supported on the server side */
186
+ export function runHydrationEvents(): void;
187
+ /** @deprecated not supported on the server side */
188
+ export function ref(
189
+ fn: () => ((element: Element) => void) | ((element: Element) => void)[],
190
+ element: Element
191
+ ): void;
192
+ /** @deprecated not supported on the server side */
193
+ export function setStyleProperty(node: Element, name: string, value: any): void;