octane 0.2.12 → 0.2.13

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.
Files changed (243) hide show
  1. package/README.md +5 -0
  2. package/dist/behavior-root.d.ts +13 -3
  3. package/dist/behavior-root.js +28 -5
  4. package/dist/cjs/behavior-root.cjs +32 -6
  5. package/dist/cjs/class-names.cjs +49 -0
  6. package/dist/cjs/constants.cjs +9 -0
  7. package/dist/cjs/css.cjs +6 -27
  8. package/dist/cjs/data-encoding.cjs +160 -0
  9. package/dist/cjs/dom-binding-handoff.cjs +93 -0
  10. package/dist/cjs/dom-binding-protocol.cjs +115 -0
  11. package/dist/cjs/dom-binding-styles.cjs +292 -0
  12. package/dist/cjs/dom-bindings.cjs +700 -0
  13. package/dist/cjs/dom-focused-move.cjs +66 -0
  14. package/dist/cjs/dom-tables.cjs +4 -94
  15. package/dist/cjs/error-codes.client.generated.cjs +33 -0
  16. package/dist/cjs/error-codes.server.generated.cjs +19 -0
  17. package/dist/cjs/hydration/control-capture.cjs +244 -0
  18. package/dist/cjs/hydration/event-capture.cjs +125 -43
  19. package/dist/cjs/hydration/interaction-config.cjs +50 -2
  20. package/dist/cjs/hydration-markers.cjs +37 -0
  21. package/dist/cjs/independent-hydration-protocol.cjs +106 -0
  22. package/dist/cjs/index.cjs +6 -0
  23. package/dist/cjs/runtime.cjs +2791 -215
  24. package/dist/cjs/runtime.server.cjs +716 -76
  25. package/dist/cjs/server/early-signals.cjs +45 -0
  26. package/dist/cjs/server/index.cjs +44 -0
  27. package/dist/cjs/server/rpc-batch.cjs +149 -0
  28. package/dist/cjs/server/rpc-stream.cjs +146 -0
  29. package/dist/cjs/server/rpc.cjs +34 -15
  30. package/dist/cjs/server/signal-query-observation.cjs +158 -0
  31. package/dist/cjs/server/streamed-region.cjs +52 -0
  32. package/dist/cjs/server/streamed-signals.cjs +512 -0
  33. package/dist/cjs/server-call.cjs +103 -0
  34. package/dist/cjs/server-rpc-batch-client.cjs +141 -0
  35. package/dist/cjs/server-rpc-client.cjs +94 -27
  36. package/dist/cjs/server-rpc-protocol.cjs +141 -0
  37. package/dist/cjs/server-rpc-stream-client.cjs +118 -0
  38. package/dist/cjs/signals/actions.cjs +474 -0
  39. package/dist/cjs/signals/client.cjs +4 -1
  40. package/dist/cjs/signals/computations.cjs +460 -0
  41. package/dist/cjs/signals/control-binding.cjs +368 -0
  42. package/dist/cjs/signals/derived-facade.cjs +50 -0
  43. package/dist/cjs/signals/document-owner.cjs +71 -0
  44. package/dist/cjs/signals/early-values.cjs +155 -0
  45. package/dist/cjs/signals/encoding.cjs +6 -95
  46. package/dist/cjs/signals/engine.cjs +276 -12
  47. package/dist/cjs/signals/errors.cjs +18 -0
  48. package/dist/cjs/signals/facade.cjs +477 -0
  49. package/dist/cjs/signals/graph.cjs +163 -20
  50. package/dist/cjs/signals/handle-protocol.cjs +36 -0
  51. package/dist/cjs/signals/index.cjs +81 -2
  52. package/dist/cjs/signals/native-read-client.cjs +10 -0
  53. package/dist/cjs/signals/owner-context.cjs +112 -0
  54. package/dist/cjs/signals/query-attempt-observer.cjs +68 -0
  55. package/dist/cjs/signals/query-facade.cjs +72 -0
  56. package/dist/cjs/signals/read-protocol.cjs +32 -0
  57. package/dist/cjs/signals/requests.cjs +287 -14
  58. package/dist/cjs/signals/scalar-computations.cjs +76 -0
  59. package/dist/cjs/signals/server.cjs +4 -1
  60. package/dist/cjs/signals/transition-candidate.cjs +567 -0
  61. package/dist/cjs/signals/transition-state.cjs +106 -0
  62. package/dist/cjs/signals/types.cjs +50 -0
  63. package/dist/cjs/stream-protocol.cjs +3 -0
  64. package/dist/cjs/streamed-signals-protocol.cjs +159 -0
  65. package/dist/cjs/style-values.cjs +122 -0
  66. package/dist/cjs/version.cjs +1 -1
  67. package/dist/class-names.d.ts +5 -0
  68. package/dist/class-names.js +25 -0
  69. package/dist/compiler/bundler.js +34 -6
  70. package/dist/compiler/compile.js +2234 -559
  71. package/dist/compiler/dom-binding-program.js +935 -0
  72. package/dist/compiler/dom-binding-request.js +57 -0
  73. package/dist/compiler/dom-bindings.js +2245 -0
  74. package/dist/compiler/hook-deps.js +26 -0
  75. package/dist/compiler/hydrate-boundaries.js +358 -15
  76. package/dist/compiler/index.d.ts +38 -1
  77. package/dist/compiler/index.js +1 -0
  78. package/dist/compiler/native-attribute-reads.js +127 -0
  79. package/dist/compiler/native-read-diagnostics.js +48 -9
  80. package/dist/compiler/native-read-types.js +55 -32
  81. package/dist/compiler/server-context.js +118 -0
  82. package/dist/compiler/signal-attempt-reads.js +479 -0
  83. package/dist/compiler/signal-declarations.js +557 -0
  84. package/dist/compiler/signal-start-reads.js +413 -0
  85. package/dist/compiler/slot-hooks.js +57 -10
  86. package/dist/compiler/template-ir.js +200 -0
  87. package/dist/compiler/typescript.d.ts +2 -0
  88. package/dist/compiler/typescript.js +2 -0
  89. package/dist/compiler/vite.d.ts +3 -1
  90. package/dist/compiler/vite.js +122 -4
  91. package/dist/compiler/volar.d.ts +6 -1
  92. package/dist/compiler/volar.js +674 -143
  93. package/dist/constants.d.ts +1 -0
  94. package/dist/constants.js +10 -0
  95. package/dist/css.d.ts +2 -5
  96. package/dist/css.js +2 -23
  97. package/dist/data-encoding.d.ts +9 -0
  98. package/dist/data-encoding.js +134 -0
  99. package/dist/dom-binding-classes.d.ts +15 -0
  100. package/dist/dom-binding-classes.js +129 -0
  101. package/dist/dom-binding-controls.d.ts +2 -0
  102. package/dist/dom-binding-controls.js +6 -0
  103. package/dist/dom-binding-handoff.d.ts +55 -0
  104. package/dist/dom-binding-handoff.js +62 -0
  105. package/dist/dom-binding-program.d.ts +300 -0
  106. package/dist/dom-binding-program.js +1625 -0
  107. package/dist/dom-binding-projections.d.ts +15 -0
  108. package/dist/dom-binding-projections.js +187 -0
  109. package/dist/dom-binding-protocol.d.ts +13 -0
  110. package/dist/dom-binding-protocol.js +88 -0
  111. package/dist/dom-binding-signals.d.ts +21 -0
  112. package/dist/dom-binding-signals.js +109 -0
  113. package/dist/dom-binding-styles.d.ts +17 -0
  114. package/dist/dom-binding-styles.js +272 -0
  115. package/dist/dom-bindings.d.ts +89 -0
  116. package/dist/dom-bindings.js +670 -0
  117. package/dist/dom-focused-move.d.ts +6 -0
  118. package/dist/dom-focused-move.js +42 -0
  119. package/dist/dom-tables.d.ts +1 -3
  120. package/dist/dom-tables.js +1 -91
  121. package/dist/error-codes.client.generated.d.ts +9 -0
  122. package/dist/error-codes.client.generated.js +33 -0
  123. package/dist/error-codes.server.generated.d.ts +5 -0
  124. package/dist/error-codes.server.generated.js +19 -0
  125. package/dist/hydration/control-capture.d.ts +62 -0
  126. package/dist/hydration/control-capture.js +223 -0
  127. package/dist/hydration/document-lifecycle.d.ts +23 -0
  128. package/dist/hydration/document-lifecycle.js +80 -0
  129. package/dist/hydration/event-capture.d.ts +20 -1
  130. package/dist/hydration/event-capture.js +128 -42
  131. package/dist/hydration/independent-island.d.ts +45 -0
  132. package/dist/hydration/independent-island.js +233 -0
  133. package/dist/hydration/index.d.ts +8 -1
  134. package/dist/hydration/index.js +55 -1
  135. package/dist/hydration/interaction-config.d.ts +5 -0
  136. package/dist/hydration/interaction-config.js +44 -1
  137. package/dist/hydration/stream-delivery.d.ts +32 -0
  138. package/dist/hydration/stream-delivery.js +333 -0
  139. package/dist/hydration/stream-receiver.d.ts +26 -0
  140. package/dist/hydration/stream-receiver.js +204 -0
  141. package/dist/hydration/stream-result-receiver.d.ts +70 -0
  142. package/dist/hydration/stream-result-receiver.js +246 -0
  143. package/dist/hydration/streamed-signals.d.ts +44 -0
  144. package/dist/hydration/streamed-signals.js +186 -0
  145. package/dist/hydration/types.d.ts +6 -0
  146. package/dist/hydration-markers.d.ts +7 -0
  147. package/dist/hydration-markers.js +10 -0
  148. package/dist/independent-hydration-protocol.d.ts +31 -0
  149. package/dist/independent-hydration-protocol.js +80 -0
  150. package/dist/index.d.ts +2 -0
  151. package/dist/index.js +4 -0
  152. package/dist/internal/signal-read.d.ts +1 -0
  153. package/dist/internal/signal-read.js +4 -0
  154. package/dist/jsx-runtime.d.ts +45 -6
  155. package/dist/public-types.d.ts +15 -1
  156. package/dist/runtime.d.ts +259 -21
  157. package/dist/runtime.js +2812 -220
  158. package/dist/runtime.server.d.ts +86 -6
  159. package/dist/runtime.server.js +712 -76
  160. package/dist/server/early-signals.d.ts +14 -0
  161. package/dist/server/early-signals.js +34 -0
  162. package/dist/server/index.d.ts +10 -2
  163. package/dist/server/index.js +48 -1
  164. package/dist/server/rpc-batch.d.ts +17 -0
  165. package/dist/server/rpc-batch.js +129 -0
  166. package/dist/server/rpc-stream.d.ts +9 -0
  167. package/dist/server/rpc-stream.js +125 -0
  168. package/dist/server/rpc.d.ts +5 -1
  169. package/dist/server/rpc.js +37 -13
  170. package/dist/server/signal-query-observation.d.ts +3 -0
  171. package/dist/server/signal-query-observation.js +134 -0
  172. package/dist/server/streamed-region.d.ts +15 -0
  173. package/dist/server/streamed-region.js +30 -0
  174. package/dist/server/streamed-signals.d.ts +45 -0
  175. package/dist/server/streamed-signals.js +488 -0
  176. package/dist/server-call.d.ts +41 -0
  177. package/dist/server-call.js +75 -0
  178. package/dist/server-rpc-batch-client.d.ts +7 -0
  179. package/dist/server-rpc-batch-client.js +119 -0
  180. package/dist/server-rpc-client.d.ts +3 -1
  181. package/dist/server-rpc-client.js +99 -27
  182. package/dist/server-rpc-protocol.d.ts +47 -0
  183. package/dist/server-rpc-protocol.js +109 -0
  184. package/dist/server-rpc-stream-client.d.ts +5 -0
  185. package/dist/server-rpc-stream-client.js +98 -0
  186. package/dist/signals/actions.d.ts +12 -0
  187. package/dist/signals/actions.js +466 -0
  188. package/dist/signals/client.d.ts +2 -0
  189. package/dist/signals/client.js +1 -0
  190. package/dist/signals/computations.d.ts +37 -0
  191. package/dist/signals/computations.js +455 -0
  192. package/dist/signals/control-binding.d.ts +31 -0
  193. package/dist/signals/control-binding.js +353 -0
  194. package/dist/signals/derived-facade.d.ts +3 -0
  195. package/dist/signals/derived-facade.js +25 -0
  196. package/dist/signals/document-owner.d.ts +10 -0
  197. package/dist/signals/document-owner.js +43 -0
  198. package/dist/signals/early-values.d.ts +24 -0
  199. package/dist/signals/early-values.js +124 -0
  200. package/dist/signals/encoding.d.ts +1 -3
  201. package/dist/signals/encoding.js +3 -93
  202. package/dist/signals/engine.d.ts +53 -4
  203. package/dist/signals/engine.js +275 -16
  204. package/dist/signals/errors.d.ts +7 -0
  205. package/dist/signals/errors.js +16 -0
  206. package/dist/signals/facade.d.ts +74 -0
  207. package/dist/signals/facade.js +452 -0
  208. package/dist/signals/graph.d.ts +50 -5
  209. package/dist/signals/graph.js +170 -19
  210. package/dist/signals/handle-protocol.d.ts +4 -0
  211. package/dist/signals/handle-protocol.js +11 -0
  212. package/dist/signals/index.d.ts +12 -3
  213. package/dist/signals/index.js +71 -2
  214. package/dist/signals/native-read-client.d.ts +3 -0
  215. package/dist/signals/native-read-client.js +10 -0
  216. package/dist/signals/owner-context.d.ts +22 -0
  217. package/dist/signals/owner-context.js +77 -0
  218. package/dist/signals/query-attempt-observer.d.ts +49 -0
  219. package/dist/signals/query-attempt-observer.js +41 -0
  220. package/dist/signals/query-facade.d.ts +3 -0
  221. package/dist/signals/query-facade.js +49 -0
  222. package/dist/signals/read-protocol.d.ts +32 -3
  223. package/dist/signals/read-protocol.js +26 -0
  224. package/dist/signals/requests.d.ts +38 -5
  225. package/dist/signals/requests.js +298 -15
  226. package/dist/signals/scalar-computations.d.ts +2 -0
  227. package/dist/signals/scalar-computations.js +60 -0
  228. package/dist/signals/server.d.ts +2 -0
  229. package/dist/signals/server.js +1 -0
  230. package/dist/signals/transition-candidate.d.ts +71 -0
  231. package/dist/signals/transition-candidate.js +557 -0
  232. package/dist/signals/transition-state.d.ts +51 -0
  233. package/dist/signals/transition-state.js +70 -0
  234. package/dist/signals/types.d.ts +95 -5
  235. package/dist/signals/types.js +20 -0
  236. package/dist/stream-protocol.d.ts +0 -5
  237. package/dist/stream-protocol.js +3 -0
  238. package/dist/streamed-signals-protocol.d.ts +60 -0
  239. package/dist/streamed-signals-protocol.js +130 -0
  240. package/dist/style-values.d.ts +3 -0
  241. package/dist/style-values.js +96 -0
  242. package/dist/version.js +1 -1
  243. package/package.json +37 -1
@@ -0,0 +1,455 @@
1
+ import { createDerivedCellWith } from "./engine.js";
2
+ import {
3
+ ScopedNode,
4
+ CandidateUnsupportedError,
5
+ assertAlive,
6
+ attachObserver,
7
+ derivedValueState,
8
+ errorState,
9
+ invalidateNode,
10
+ isThenable,
11
+ pendingState,
12
+ publishNode,
13
+ readNode,
14
+ refreshNode,
15
+ readyState,
16
+ signalBatch,
17
+ subscribeNode,
18
+ untrack,
19
+ untrackCommitted
20
+ } from "./graph.js";
21
+ import { SIGNAL_DEPENDENT_NODE } from "./read-protocol.js";
22
+ import {
23
+ SIGNAL_OWNER_RESOLVE
24
+ } from "./types.js";
25
+ function createDeclaredDerivedCell(owner, key, compute, options) {
26
+ return createDerivedCellWith(owner, key, compute, options, DerivedBinding);
27
+ }
28
+ function attempt(binding) {
29
+ let resolve;
30
+ const waiting = new Promise((done) => {
31
+ resolve = done;
32
+ });
33
+ return {
34
+ active: true,
35
+ binding,
36
+ controller: void 0,
37
+ iterator: void 0,
38
+ dependencies: /* @__PURE__ */ new Map(),
39
+ waiting,
40
+ resolve,
41
+ hasYielded: false,
42
+ owners: /* @__PURE__ */ new Set(),
43
+ cancelWaiting: void 0,
44
+ cancelRead: void 0
45
+ };
46
+ }
47
+ function ignoreRetiredCloseFailure() {
48
+ }
49
+ function closeIterator(iterator) {
50
+ try {
51
+ Promise.resolve(untrackCommitted(() => iterator.return?.())).catch(ignoreRetiredCloseFailure);
52
+ } catch {
53
+ }
54
+ }
55
+ function asyncIterator(value) {
56
+ if (typeof value !== "object" && typeof value !== "function" || value === null) return;
57
+ const factory = value[Symbol.asyncIterator];
58
+ return typeof factory === "function" ? () => factory.call(value) : void 0;
59
+ }
60
+ function resolveHandle(handle$, owner) {
61
+ const resolved = SIGNAL_OWNER_RESOLVE in handle$ ? handle$[SIGNAL_OWNER_RESOLVE](owner) : handle$;
62
+ if (!(resolved instanceof ScopedNode)) {
63
+ throw new TypeError("Attempt reads require an Octane signal handle.");
64
+ }
65
+ return resolved;
66
+ }
67
+ class DerivedBinding {
68
+ constructor(owner, node, compute, options) {
69
+ this.owner = owner;
70
+ this.node = node;
71
+ this.options = options;
72
+ this.compute = compute;
73
+ node.compute = () => this.evaluate();
74
+ }
75
+ owner;
76
+ node;
77
+ options;
78
+ current;
79
+ compute;
80
+ frozen = false;
81
+ candidate;
82
+ forkCandidate(target, frame) {
83
+ if (this.frozen || this.owner.readBarrier || !this.compute) {
84
+ throw new CandidateUnsupportedError("Frozen derived candidates are not supported.");
85
+ }
86
+ const fork = new DerivedBinding(this.owner, target, this.compute, this.options);
87
+ fork.candidate = frame;
88
+ return {
89
+ dispose: () => fork.dispose(),
90
+ dependencies: () => fork.current?.dependencies.keys() ?? [],
91
+ prepare: () => {
92
+ const state = target.state;
93
+ if (state?.snapshot.status !== "ready" && state?.snapshot.status !== "error")
94
+ return state?.waiting ? { status: "pending", waiting: state.waiting } : { status: "invalid" };
95
+ const current = fork.current;
96
+ const previous = this.current;
97
+ return {
98
+ status: "ready",
99
+ receipt: {
100
+ validate: () => !this.owner.retired && this.owner.readBarrier === void 0 && this.compute !== void 0 && this.current === previous && fork.current === current && target.state === state && (!current || current.binding === fork && fork.validDependencies(current)),
101
+ publish: () => {
102
+ this.current = current;
103
+ if (current) current.binding = this;
104
+ this.node.invalidateAttempt = current ? () => this.invalidateGraph() : void 0;
105
+ fork.current = void 0;
106
+ fork.candidate = void 0;
107
+ target.invalidateAttempt = void 0;
108
+ return () => {
109
+ if (previous !== this.current) this.stop(previous);
110
+ };
111
+ },
112
+ accept: () => {
113
+ if (!current) return;
114
+ const dependencies = [...current.dependencies.values()];
115
+ const releases = [];
116
+ current.dependencies.clear();
117
+ for (const dependency of dependencies) {
118
+ releases.push(dependency.unsubscribe);
119
+ dependency.node = frame.canonical(dependency.node);
120
+ dependency.revision = dependency.node.revision;
121
+ dependency.unsubscribe = attachObserver(
122
+ dependency.node,
123
+ DerivedBinding.notify(current),
124
+ true
125
+ );
126
+ current.dependencies.set(dependency.node, dependency);
127
+ }
128
+ for (const release of releases) release();
129
+ }
130
+ }
131
+ };
132
+ }
133
+ };
134
+ }
135
+ static context(current) {
136
+ return {
137
+ get signal() {
138
+ if (!current.active) return AbortSignal.abort();
139
+ return (current.controller ??= new AbortController()).signal;
140
+ },
141
+ read(handle$) {
142
+ return current.binding ? current.binding.read(current, handle$) : Promise.reject(new Error("The derived attempt is no longer active."));
143
+ }
144
+ };
145
+ }
146
+ static notify(current) {
147
+ const notify = () => current.binding?.invalidate(current);
148
+ notify[SIGNAL_DEPENDENT_NODE] = current.binding.node;
149
+ return notify;
150
+ }
151
+ read(current, handle$) {
152
+ if (!current.active)
153
+ return Promise.reject(new Error("The derived attempt is no longer active."));
154
+ try {
155
+ return DerivedBinding.readValue(current, this.readDependency(current, handle$));
156
+ } catch (error) {
157
+ return Promise.reject(error);
158
+ }
159
+ }
160
+ readDependency(current, handle$) {
161
+ const dependency = this.candidate ? this.candidate.run(() => this.candidate.resolve(resolveHandle(handle$, this.owner))) : resolveHandle(handle$, this.owner);
162
+ if (dependency === this.node) {
163
+ throw new TypeError("A derived signal cannot read itself.");
164
+ }
165
+ assertAlive(dependency.owner);
166
+ let lease = current.dependencies.get(dependency);
167
+ if (!lease) {
168
+ const unsubscribe = subscribeNode(dependency, DerivedBinding.notify(current));
169
+ const revision = dependency.revision;
170
+ lease = { node: dependency, revision, unsubscribe };
171
+ current.dependencies.set(dependency, lease);
172
+ }
173
+ return lease;
174
+ }
175
+ static async readValue(current, dependency) {
176
+ while (current.active) {
177
+ const state = untrack(
178
+ () => current.binding.candidate ? current.binding.candidate.run(() => readNode(dependency.node)) : readNode(dependency.node)
179
+ );
180
+ if (!current.active) break;
181
+ if (state.snapshot.status === "ready") {
182
+ if (dependency.node.owner !== current.binding.owner)
183
+ current.owners.add(dependency.node.owner);
184
+ if (state.owners) {
185
+ for (const owner of state.owners)
186
+ if (owner !== current.binding.owner) current.owners.add(owner);
187
+ }
188
+ return state.snapshot.value;
189
+ }
190
+ if (state.snapshot.status === "error") throw state.snapshot.error;
191
+ if (state.snapshot.status === "idle") {
192
+ throw new Error(`Signal "${dependency.node.key}" has no selected value.`);
193
+ }
194
+ current.cancelWaiting ??= new Promise((resolve) => {
195
+ current.cancelRead = resolve;
196
+ });
197
+ await Promise.race([state.waiting, current.cancelWaiting]);
198
+ }
199
+ throw new Error("The derived attempt is no longer active.");
200
+ }
201
+ valid(current) {
202
+ if (!current.active || this.current !== current || this.owner.retired || this.owner.readBarrier !== void 0)
203
+ return false;
204
+ return this.validDependencies(current);
205
+ }
206
+ validDependencies(current) {
207
+ for (const dependency of current.dependencies.values()) {
208
+ if (dependency.node.owner.retired || dependency.node.revision !== dependency.revision) {
209
+ return false;
210
+ }
211
+ }
212
+ return true;
213
+ }
214
+ evaluate() {
215
+ if (this.owner.readBarrier !== void 0) {
216
+ this.frozen = true;
217
+ return this.node.state?.snapshot.status === "ready" ? this.node.state : pendingState(this.owner.readBarrier);
218
+ }
219
+ this.stop(this.current);
220
+ this.current = void 0;
221
+ this.node.invalidateAttempt = void 0;
222
+ const compute = this.compute;
223
+ let current = compute.length ? attempt(this) : void 0;
224
+ let result;
225
+ try {
226
+ result = current ? compute(DerivedBinding.context(current)) : compute();
227
+ } catch (error) {
228
+ this.stop(current);
229
+ if (isThenable(error)) throw error;
230
+ return errorState(error);
231
+ }
232
+ if (this.options?.sync) {
233
+ this.stop(current, false);
234
+ return derivedValueState(this.node, result);
235
+ }
236
+ let iteratorFactory;
237
+ let thenable = false;
238
+ try {
239
+ iteratorFactory = asyncIterator(result);
240
+ thenable = isThenable(result);
241
+ } catch (error) {
242
+ this.stop(current);
243
+ return errorState(error);
244
+ }
245
+ if (!thenable && !iteratorFactory) {
246
+ this.stop(current, false);
247
+ return derivedValueState(this.node, result);
248
+ }
249
+ current ??= attempt(this);
250
+ this.current = current;
251
+ this.node.invalidateAttempt = () => this.invalidateGraph();
252
+ if (iteratorFactory) this.observeIterator(current, iteratorFactory);
253
+ else DerivedBinding.observePromise(current, result);
254
+ return pendingState(
255
+ current.waiting,
256
+ iteratorFactory ? "connecting" : "none",
257
+ void 0,
258
+ current.resolve
259
+ );
260
+ }
261
+ static observePromise(current, result) {
262
+ Promise.resolve(result).then(
263
+ (value) => {
264
+ const binding = current.binding;
265
+ if (!binding?.valid(current)) return;
266
+ let iteratorFactory;
267
+ try {
268
+ iteratorFactory = asyncIterator(value);
269
+ } catch (error) {
270
+ binding.fail(current, error);
271
+ return;
272
+ }
273
+ if (iteratorFactory) {
274
+ signalBatch(
275
+ () => publishNode(
276
+ binding.node,
277
+ pendingState(current.waiting, "connecting", void 0, current.resolve)
278
+ )
279
+ );
280
+ binding.observeIterator(current, iteratorFactory);
281
+ return;
282
+ }
283
+ binding.accept(current, readyState(value));
284
+ },
285
+ (error) => current.binding?.fail(current, error)
286
+ );
287
+ }
288
+ observeIterator(current, iteratorFactory) {
289
+ try {
290
+ const iterator = untrack(iteratorFactory);
291
+ if (!this.valid(current)) {
292
+ closeIterator(iterator);
293
+ return;
294
+ }
295
+ current.iterator = iterator;
296
+ } catch (error) {
297
+ this.fail(current, error);
298
+ return;
299
+ }
300
+ this.next(current);
301
+ }
302
+ next(current) {
303
+ if (!this.valid(current) || !current.iterator) return;
304
+ let step;
305
+ try {
306
+ step = untrack(() => current.iterator.next());
307
+ } catch (error) {
308
+ this.fail(current, error);
309
+ return;
310
+ }
311
+ DerivedBinding.observeStep(current, step);
312
+ }
313
+ static queueNext(current) {
314
+ queueMicrotask(() => current.binding?.next(current));
315
+ }
316
+ static observeStep(current, step) {
317
+ Promise.resolve(step).then(
318
+ (result) => {
319
+ const binding = current.binding;
320
+ if (!binding?.valid(current)) return;
321
+ if (!result || typeof result !== "object" && typeof result !== "function") {
322
+ binding.fail(
323
+ current,
324
+ new TypeError("An async iterator must return an iteration result.")
325
+ );
326
+ return;
327
+ }
328
+ if (result.done) {
329
+ if (!current.hasYielded) {
330
+ binding.fail(current, new Error("The stream completed without yielding a value."));
331
+ return;
332
+ }
333
+ const snapshot = binding.node.state?.snapshot;
334
+ if (snapshot?.status === "ready") {
335
+ binding.accept(
336
+ current,
337
+ readyState(snapshot.value, { connection: "closed", complete: true })
338
+ );
339
+ }
340
+ return;
341
+ }
342
+ current.hasYielded = true;
343
+ binding.accept(
344
+ current,
345
+ readyState(result.value, { connection: "open", complete: false }),
346
+ false
347
+ );
348
+ DerivedBinding.queueNext(current);
349
+ },
350
+ (error) => current.binding?.fail(current, error)
351
+ );
352
+ }
353
+ accept(current, state, complete = true) {
354
+ if (!this.valid(current)) {
355
+ this.invalidate(current);
356
+ return;
357
+ }
358
+ if (state.snapshot.status === "ready") {
359
+ state = derivedValueState(
360
+ this.node,
361
+ state.snapshot.value,
362
+ state.snapshot,
363
+ current.dependencies.size ? current.dependencies.keys() : void 0
364
+ );
365
+ }
366
+ const previousOwners = this.node.state?.owners;
367
+ if (previousOwners) for (const owner of previousOwners) current.owners.add(owner);
368
+ const published = current.owners.size ? { ...state, owners: current.owners } : state;
369
+ signalBatch(() => publishNode(this.node, published));
370
+ if (complete) this.finish(current);
371
+ }
372
+ fail(current, error) {
373
+ if (!this.valid(current)) return;
374
+ signalBatch(
375
+ () => publishNode(this.node, errorState(error, current.iterator ? "closed" : "none"))
376
+ );
377
+ this.finish(current);
378
+ }
379
+ finish(current) {
380
+ if (this.current !== current) return;
381
+ current.active = false;
382
+ current.controller = void 0;
383
+ current.iterator = void 0;
384
+ current.cancelRead?.();
385
+ current.cancelWaiting = void 0;
386
+ current.cancelRead = void 0;
387
+ current.resolve();
388
+ }
389
+ invalidate(current) {
390
+ if (this.current !== current || this.owner.retired) return;
391
+ this.stop(current);
392
+ this.current = void 0;
393
+ signalBatch(() => {
394
+ invalidateNode(this.node);
395
+ refreshNode(this.node);
396
+ });
397
+ }
398
+ invalidateGraph() {
399
+ const current = this.current;
400
+ if (!current) return;
401
+ this.stop(current);
402
+ if (this.current === current) this.current = void 0;
403
+ }
404
+ stop(current, cancel = true) {
405
+ if (!current) return;
406
+ const active = current.active;
407
+ const controller = current.controller;
408
+ const iterator = current.iterator;
409
+ current.active = false;
410
+ current.binding = void 0;
411
+ current.controller = void 0;
412
+ current.iterator = void 0;
413
+ current.owners = void 0;
414
+ for (const dependency of current.dependencies.values()) dependency.unsubscribe();
415
+ current.dependencies.clear();
416
+ current.cancelRead?.();
417
+ current.cancelWaiting = void 0;
418
+ current.cancelRead = void 0;
419
+ current.resolve();
420
+ if (!cancel || !active) return;
421
+ if (controller) untrackCommitted(() => controller.abort());
422
+ if (iterator) closeIterator(iterator);
423
+ }
424
+ /** Stop only unfinished asynchronous reads; settled dependency edges stay live. */
425
+ suspend() {
426
+ if (!this.current?.active) return false;
427
+ this.frozen = true;
428
+ const current = this.current;
429
+ this.current = void 0;
430
+ this.node.invalidateAttempt = void 0;
431
+ if (this.node.state?.snapshot.status !== "ready") {
432
+ this.node.state = pendingState(this.owner.readBarrier);
433
+ }
434
+ this.stop(current);
435
+ return true;
436
+ }
437
+ resume() {
438
+ if (!this.frozen || this.owner.retired || this.owner.readBarrier !== void 0 || !this.compute)
439
+ return;
440
+ this.frozen = false;
441
+ invalidateNode(this.node);
442
+ refreshNode(this.node);
443
+ }
444
+ dispose() {
445
+ this.stop(this.current);
446
+ this.current = void 0;
447
+ this.compute = void 0;
448
+ this.candidate = void 0;
449
+ this.node.invalidateAttempt = void 0;
450
+ }
451
+ }
452
+ export {
453
+ DerivedBinding,
454
+ createDeclaredDerivedCell
455
+ };
@@ -0,0 +1,31 @@
1
+ import { type SignalHandle } from './types.js';
2
+ type SignalControl = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;
3
+ type ControlChannel = 'value' | 'checked';
4
+ export interface BindingControlPrepared {
5
+ /** Publish captured native edits and switch input authority, without writing DOM. */
6
+ publish(): void;
7
+ /** Commit only a still-current, fully validated native value. */
8
+ commit(): void;
9
+ }
10
+ export interface BindingControlPreview extends BindingControlPrepared {
11
+ validate(): boolean;
12
+ discard(): void;
13
+ }
14
+ export interface BindingControlLease {
15
+ prepare(value: unknown): BindingControlPrepared;
16
+ preview(value: unknown): BindingControlPreview;
17
+ prepareCurrent(): BindingControlPrepared;
18
+ dispose(): void;
19
+ }
20
+ /** @internal Optional compiled-control capability; captures, but never creates, an owner. */
21
+ export declare function __createBindingControls(): {
22
+ claim(element: Element, channel: ControlChannel, notify: () => void): BindingControlLease;
23
+ };
24
+ /**
25
+ * Bind one native property on externally owned DOM without creating a renderer.
26
+ * Writable signals adopt captured early edits and receive native input; other
27
+ * handles only project. Dispose before transferring the property to another owner.
28
+ */
29
+ export declare function bindSignalControl(control: SignalControl, channel: 'value', handle$: SignalHandle<string | readonly string[]>): () => void;
30
+ export declare function bindSignalControl(control: HTMLInputElement, channel: 'checked', handle$: SignalHandle<boolean>): () => void;
31
+ export {};