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,74 @@
1
+ import { NATIVE_DOM_VALUE } from './read-protocol.js';
2
+ export { isSignalHandle, isWritableSignal } from './handle-protocol.js';
3
+ import { SIGNAL_HANDLE, SIGNAL_BINDING_IDENTITY, SIGNAL_BINDING_READ, SIGNAL_BINDING_SUBSCRIBE, SIGNAL_OWNER_RESOLVE, type DerivedCompute, type DerivedOptions, type DerivedSignal, type OwnerBoundSignal, type Scope, type ScopeSeed, type SignalHandle, type SignalOptions, type SignalOwner, type SignalOwnerIdentity, type SignalSnapshot, type WritableSignal } from './types.js';
4
+ import type { StreamFrameIdentity, StreamedSignalResultFrame } from '../streamed-signals-protocol.js';
5
+ /** @internal Install initial response data before this document creates any live cells. */
6
+ export declare function initializeDocumentSignalOwner(owner: SignalOwnerIdentity, seed: ScopeSeed): void;
7
+ /** @internal A document may freeze read work without retiring data or accepted writes. */
8
+ export declare function createSignalOwnerLifecycle(owner: SignalOwner): {
9
+ readonly retired: boolean;
10
+ freeze(): void;
11
+ resume(): void;
12
+ retire(): void;
13
+ };
14
+ /** @internal Resolve a public descriptor in the current declaration owner. */
15
+ export declare function resolveCurrentSignalHandle<T>(handle$: SignalHandle<T>): SignalHandle<T>;
16
+ /** @internal Resolve a descriptor against a captured renderer/request owner. */
17
+ export declare function resolveSignalHandleForOwner<T>(handle$: SignalHandle<T>, owner: SignalOwner): SignalHandle<T>;
18
+ /** @internal Resolve a descriptor against an already selected signal scope. */
19
+ export declare function resolveSignalHandleForScope<T>(handle$: SignalHandle<T>, owner: Scope): SignalHandle<T>;
20
+ /** @internal Shared owner resolution for statically selected signal factories. */
21
+ export declare abstract class Descriptor<T, H extends SignalHandle<T>> implements OwnerBoundSignal<T> {
22
+ readonly key: string;
23
+ readonly kind: H['kind'];
24
+ private readonly create;
25
+ private readonly site;
26
+ readonly [SIGNAL_HANDLE]: true;
27
+ private readonly cells;
28
+ constructor(key: string, kind: H['kind'], create: (owner: Scope) => H, site: string | undefined);
29
+ [SIGNAL_OWNER_RESOLVE](owner: Scope): H;
30
+ private resolvedCell;
31
+ protected resolve(): H;
32
+ get(): T;
33
+ [NATIVE_DOM_VALUE](): T;
34
+ [SIGNAL_BINDING_READ](): T;
35
+ [SIGNAL_BINDING_SUBSCRIBE](notify: () => void, onRetire?: () => void): () => void;
36
+ [SIGNAL_BINDING_IDENTITY](): {
37
+ scope: "document" | "instance";
38
+ nodeKey: string;
39
+ };
40
+ latest(): T | undefined;
41
+ latest<F>(fallback: F): T | F;
42
+ snapshot(): SignalSnapshot<T>;
43
+ subscribe(notify: () => void): () => void;
44
+ }
45
+ /** @internal Scalar and general derivations share the same public handle. */
46
+ export declare class DerivedDescriptor<T> extends Descriptor<T, DerivedSignal<T>> implements DerivedSignal<T> {
47
+ readonly kind: 'derived';
48
+ }
49
+ /** @internal Preserve authored or compiler-assigned declaration identity. */
50
+ export declare function descriptorKey(site: string | undefined, explicit: string | undefined): string;
51
+ /** @internal Read authored identity once, without interpreting initial data as a key. */
52
+ export declare function signalOptionsKey(options?: SignalOptions): string | undefined;
53
+ export declare function __signalAt<T>(site: string | undefined, initial: T, options?: SignalOptions): WritableSignal<T>;
54
+ export declare function signal$<T>(initial: T, options?: SignalOptions): WritableSignal<T>;
55
+ /** Compiler-only scalar proof; authored derived$ remains dynamically asynchronous. */
56
+ export declare function __derivedScalarAt<T>(site: string | undefined, compute: DerivedCompute<T>, options?: DerivedOptions & SignalOptions): DerivedSignal<T>;
57
+ export declare function readSignalBinding<T>(handle$: SignalHandle<T>): T;
58
+ /** @internal Start compiler-proven independent reads without consuming their results. */
59
+ export declare function __startSignalReads(handles: readonly SignalHandle<unknown>[], primitive?: boolean): void;
60
+ /** Bind receiver-owned selection authority, optionally before the query descriptor resolves. */
61
+ export declare function bindStreamedSignalSelection(owner: SignalOwner, identity: StreamFrameIdentity): boolean;
62
+ /** Accept one already-validated result frame without reviving a retired owner. */
63
+ export declare function acceptStreamedSignalResult(owner: SignalOwner, frame: StreamedSignalResultFrame): boolean;
64
+ /** Fail one exact result channel without exposing an untrusted remote stack. */
65
+ export declare function failStreamedSignalResult(owner: SignalOwner, identity: StreamFrameIdentity, code: string): boolean;
66
+ interface StreamedSignalReceiver {
67
+ attachResult(identity: StreamFrameIdentity, consumer: {
68
+ accept(frame: StreamedSignalResultFrame): void | false;
69
+ retainCompleted?(frames: StreamedSignalResultFrame[]): boolean;
70
+ fail(error: any): void;
71
+ }): () => void;
72
+ }
73
+ /** Connect a neutral early receiver to the signals engine without a hydration dependency. */
74
+ export declare function attachStreamedSignalResult(receiver: StreamedSignalReceiver, owner: SignalOwner, identity: StreamFrameIdentity): () => void;
@@ -0,0 +1,452 @@
1
+ import {
2
+ acceptScopeStreamedResult,
3
+ bindScopeStreamedSelection,
4
+ createDeclaredSignalCell,
5
+ createScope,
6
+ failScopeStreamedResult,
7
+ ScopeImpl
8
+ } from "./engine.js";
9
+ import { createDeclaredScalarCell } from "./scalar-computations.js";
10
+ import { ScopeDisposedError, SignalStreamError } from "./errors.js";
11
+ import { isThenable, readSignalBinding as readBinding, untrack } from "./graph.js";
12
+ import { readEarlySignalValue } from "./early-values.js";
13
+ import { NATIVE_DOM_VALUE, forwardNativeTransitionConsumer } from "./read-protocol.js";
14
+ import { isSignalHandle } from "./handle-protocol.js";
15
+ import { isSignalHandle as isSignalHandle2, isWritableSignal } from "./handle-protocol.js";
16
+ import {
17
+ captureSignalOwner,
18
+ currentSignalOwner,
19
+ installSignalOwnerRetirement,
20
+ runWithSignalOwner
21
+ } from "./owner-context.js";
22
+ import {
23
+ SIGNAL_HANDLE,
24
+ SIGNAL_BINDING_IDENTITY,
25
+ SIGNAL_BINDING_READ,
26
+ SIGNAL_BINDING_SUBSCRIBE,
27
+ SIGNAL_OWNER_RESOLVE
28
+ } from "./types.js";
29
+ const identityScopes = /* @__PURE__ */ new WeakMap();
30
+ const scopeOwners = /* @__PURE__ */ new WeakMap();
31
+ const retiredIdentities = /* @__PURE__ */ new WeakSet();
32
+ const documentInstances = /* @__PURE__ */ new WeakMap();
33
+ const instanceDocuments = /* @__PURE__ */ new WeakMap();
34
+ const frozenDocuments = /* @__PURE__ */ new WeakMap();
35
+ function isScope(owner) {
36
+ return typeof owner.signal$ === "function";
37
+ }
38
+ function isRendererOwner(owner) {
39
+ return "documentOwner" in owner && "instanceOwner" in owner && typeof owner.instanceKey === "string";
40
+ }
41
+ function resolveIdentity(identity, scopeKey, owner) {
42
+ if (retiredIdentities.has(identity)) throw new ScopeDisposedError(scopeKey);
43
+ let scope = identityScopes.get(identity);
44
+ if (!scope) {
45
+ scope = createScope({ scopeKey });
46
+ identityScopes.set(identity, scope);
47
+ scopeOwners.set(scope, owner);
48
+ const barrier = frozenDocuments.get(isRendererOwner(owner) ? owner.documentOwner : owner);
49
+ if (barrier !== void 0) scope.readBarrier = barrier;
50
+ }
51
+ return scope;
52
+ }
53
+ function initializeDocumentSignalOwner(owner, seed) {
54
+ if (isScope(owner) || isRendererOwner(owner)) {
55
+ throw new TypeError("Initial document signals require an implicit document owner.");
56
+ }
57
+ if (retiredIdentities.has(owner)) throw new ScopeDisposedError(owner.scopeKey);
58
+ if (identityScopes.has(owner)) {
59
+ throw new Error(
60
+ "Initial document signals must be installed once, before any signal reads or writes."
61
+ );
62
+ }
63
+ const scope = createScope({ scopeKey: owner.scopeKey, seed });
64
+ const barrier = frozenDocuments.get(owner);
65
+ if (barrier !== void 0) scope.readBarrier = barrier;
66
+ identityScopes.set(owner, scope);
67
+ scopeOwners.set(scope, owner);
68
+ }
69
+ function resolveOwner(owner) {
70
+ if (isScope(owner)) return owner;
71
+ if (isRendererOwner(owner)) {
72
+ if (!isScope(owner.documentOwner) && retiredIdentities.has(owner.documentOwner)) {
73
+ throw new ScopeDisposedError(owner.documentOwner.scopeKey);
74
+ }
75
+ if (isScope(owner.documentOwner) && owner.documentOwner.retired) {
76
+ throw new ScopeDisposedError(owner.documentOwner.scopeKey);
77
+ }
78
+ let instances = documentInstances.get(owner.documentOwner);
79
+ if (!instances) documentInstances.set(owner.documentOwner, instances = /* @__PURE__ */ new Set());
80
+ instances.add(owner.instanceOwner);
81
+ instanceDocuments.set(owner.instanceOwner, owner.documentOwner);
82
+ const documentKey = owner.documentOwner.scopeKey;
83
+ return resolveIdentity(
84
+ owner.instanceOwner,
85
+ `${documentKey}:instance:${owner.instanceKey}`,
86
+ owner
87
+ );
88
+ }
89
+ return resolveIdentity(owner, owner.scopeKey, owner);
90
+ }
91
+ function resolveDescriptorOwner(site, owner) {
92
+ if (isScope(owner)) owner = scopeOwners.get(owner) ?? owner;
93
+ if (!isRendererOwner(owner)) return resolveOwner(owner);
94
+ if (site?.startsWith("g:")) return resolveOwner(owner.documentOwner);
95
+ if (site?.startsWith("i:")) {
96
+ return resolveOwner(owner);
97
+ }
98
+ return resolveOwner(owner);
99
+ }
100
+ function existingIdentityScope(identity) {
101
+ if (retiredIdentities.has(identity)) return;
102
+ const scope = identityScopes.get(identity);
103
+ return scope?.retired ? void 0 : scope;
104
+ }
105
+ function streamedScope(owner, identity, create) {
106
+ if (isScope(owner)) {
107
+ return !owner.retired && identity.ownerKey === owner.scopeKey ? owner : void 0;
108
+ }
109
+ if (!isRendererOwner(owner)) return;
110
+ if (identity.ownerKey !== owner.documentOwner.scopeKey || identity.instanceKey !== owner.instanceKey || !identity.nodeKey.startsWith("g:") && !identity.nodeKey.startsWith("i:")) {
111
+ return;
112
+ }
113
+ const documentRetired = isScope(owner.documentOwner) ? owner.documentOwner.retired : retiredIdentities.has(owner.documentOwner);
114
+ if (documentRetired || retiredIdentities.has(owner.instanceOwner)) return;
115
+ const target = identity.nodeKey.startsWith("g:") ? owner.documentOwner : owner;
116
+ if (create) return resolveDescriptorOwner(identity.nodeKey, target);
117
+ if (isScope(target)) return target.retired ? void 0 : target;
118
+ return existingIdentityScope(isRendererOwner(target) ? target.instanceOwner : target);
119
+ }
120
+ installSignalOwnerRetirement((owner) => {
121
+ if (isScope(owner)) return;
122
+ const identity = isRendererOwner(owner) ? owner.instanceOwner : owner;
123
+ if (isRendererOwner(owner)) {
124
+ const document = instanceDocuments.get(identity);
125
+ if (document) documentInstances.get(document)?.delete(identity);
126
+ instanceDocuments.delete(identity);
127
+ } else {
128
+ const instances = documentInstances.get(identity);
129
+ if (instances) {
130
+ for (const instance of instances) {
131
+ retiredIdentities.add(instance);
132
+ const instanceScope = identityScopes.get(instance);
133
+ if (instanceScope) {
134
+ identityScopes.delete(instance);
135
+ scopeOwners.delete(instanceScope);
136
+ instanceScope.dispose();
137
+ }
138
+ instanceDocuments.delete(instance);
139
+ }
140
+ documentInstances.delete(identity);
141
+ }
142
+ }
143
+ retiredIdentities.add(identity);
144
+ const scope = identityScopes.get(identity);
145
+ if (!scope) return;
146
+ identityScopes.delete(identity);
147
+ scopeOwners.delete(scope);
148
+ scope.dispose();
149
+ });
150
+ function createSignalOwnerLifecycle(owner) {
151
+ if (isRendererOwner(owner))
152
+ throw new TypeError("A document lifecycle requires its document owner.");
153
+ let barrier;
154
+ let release;
155
+ let disposed = false;
156
+ const scopes = () => {
157
+ const result = [];
158
+ const scope = isScope(owner) ? owner : existingIdentityScope(owner);
159
+ if (scope instanceof ScopeImpl && !scope.retired) result.push(scope);
160
+ for (const instance of documentInstances.get(owner) ?? []) {
161
+ const scope2 = existingIdentityScope(instance);
162
+ if (scope2 instanceof ScopeImpl) result.push(scope2);
163
+ }
164
+ return result;
165
+ };
166
+ return {
167
+ get retired() {
168
+ return disposed || (isScope(owner) ? owner.retired : retiredIdentities.has(owner));
169
+ },
170
+ freeze() {
171
+ if (this.retired || barrier !== void 0) return;
172
+ barrier = new Promise((resolve) => {
173
+ release = resolve;
174
+ });
175
+ frozenDocuments.set(owner, barrier);
176
+ const existing = scopes();
177
+ for (const scope of existing) scope.readBarrier = barrier;
178
+ for (const scope of existing) scope.suspendReads();
179
+ },
180
+ resume() {
181
+ if (this.retired || barrier === void 0) return;
182
+ const existing = scopes();
183
+ barrier = void 0;
184
+ frozenDocuments.delete(owner);
185
+ for (const scope of existing) scope.readBarrier = void 0;
186
+ release?.();
187
+ release = void 0;
188
+ for (const scope of existing) {
189
+ if (barrier !== void 0 || this.retired) break;
190
+ scope.resumeReads();
191
+ }
192
+ },
193
+ retire() {
194
+ if (disposed) return;
195
+ disposed = true;
196
+ frozenDocuments.delete(owner);
197
+ const existing = scopes();
198
+ for (const instance of documentInstances.get(owner) ?? []) retiredIdentities.add(instance);
199
+ retiredIdentities.add(owner);
200
+ for (const scope of existing) scope.dispose();
201
+ documentInstances.delete(owner);
202
+ release?.();
203
+ release = void 0;
204
+ barrier = void 0;
205
+ }
206
+ };
207
+ }
208
+ function requireOwner() {
209
+ const owner = currentSignalOwner();
210
+ if (!owner) {
211
+ throw new Error(
212
+ "A module signal needs an active signal owner. Render it in an Octane root or use runWithSignalOwner()."
213
+ );
214
+ }
215
+ return owner;
216
+ }
217
+ function resolveCurrentSignalHandle(handle$) {
218
+ return resolveSignalHandleForOwner(handle$, requireOwner());
219
+ }
220
+ function resolveSignalHandleForOwner(handle$, owner) {
221
+ return resolveSignalHandleForScope(handle$, resolveOwner(owner));
222
+ }
223
+ function resolveSignalHandleForScope(handle$, owner) {
224
+ return SIGNAL_OWNER_RESOLVE in handle$ ? handle$[SIGNAL_OWNER_RESOLVE](owner) : handle$;
225
+ }
226
+ function requireSite(site) {
227
+ if (site) return site;
228
+ throw new Error(
229
+ "Module signal identity is assigned by the Octane compiler. Use an explicit key outside compiled code."
230
+ );
231
+ }
232
+ class Descriptor {
233
+ constructor(key, kind, create, site) {
234
+ this.key = key;
235
+ this.kind = kind;
236
+ this.create = create;
237
+ this.site = site;
238
+ }
239
+ key;
240
+ kind;
241
+ create;
242
+ site;
243
+ [SIGNAL_HANDLE] = true;
244
+ cells = /* @__PURE__ */ new WeakMap();
245
+ [SIGNAL_OWNER_RESOLVE](owner) {
246
+ requireSite(this.site);
247
+ return this.resolvedCell(resolveDescriptorOwner(this.site, owner));
248
+ }
249
+ resolvedCell(target) {
250
+ let cell = this.cells.get(target);
251
+ if (!cell) {
252
+ cell = this.create(target);
253
+ this.cells.set(target, cell);
254
+ }
255
+ return cell;
256
+ }
257
+ resolve() {
258
+ const token = requireOwner();
259
+ const owner = resolveDescriptorOwner(this.site, token);
260
+ requireSite(this.site);
261
+ return this.resolvedCell(owner);
262
+ }
263
+ get() {
264
+ return this.resolve().get();
265
+ }
266
+ [NATIVE_DOM_VALUE]() {
267
+ return this.get();
268
+ }
269
+ [SIGNAL_BINDING_READ]() {
270
+ return readBinding(this.resolve());
271
+ }
272
+ [SIGNAL_BINDING_SUBSCRIBE](notify, onRetire) {
273
+ const run = captureSignalOwner(requireOwner());
274
+ return this.resolve()[SIGNAL_BINDING_SUBSCRIBE](
275
+ forwardNativeTransitionConsumer(notify, () => run(notify)),
276
+ onRetire === void 0 ? void 0 : () => run(onRetire)
277
+ );
278
+ }
279
+ [SIGNAL_BINDING_IDENTITY]() {
280
+ return {
281
+ scope: this.site?.startsWith("g:") ? "document" : "instance",
282
+ nodeKey: this.key
283
+ };
284
+ }
285
+ latest(fallback) {
286
+ return this.resolve().latest(fallback);
287
+ }
288
+ snapshot() {
289
+ return this.resolve().snapshot();
290
+ }
291
+ subscribe(notify) {
292
+ const token = requireOwner();
293
+ const scope = resolveDescriptorOwner(this.site, token);
294
+ const run = captureSignalOwner(token);
295
+ return this[SIGNAL_OWNER_RESOLVE](scope).subscribe(
296
+ forwardNativeTransitionConsumer(notify, () => run(notify))
297
+ );
298
+ }
299
+ }
300
+ class SignalDescriptor extends Descriptor {
301
+ set(value) {
302
+ this.resolve().set(value);
303
+ }
304
+ }
305
+ class DerivedDescriptor extends Descriptor {
306
+ }
307
+ function descriptorKey(site, explicit) {
308
+ const key = explicit ?? site;
309
+ if (typeof key !== "string" || !key.trim()) return "<compiler-assigned-signal>";
310
+ return key;
311
+ }
312
+ function signalOptionsKey(options) {
313
+ if (options != null && typeof options !== "object") {
314
+ throw new TypeError("Signal declaration options must be an object.");
315
+ }
316
+ const key = options?.key;
317
+ if (key !== void 0 && (typeof key !== "string" || !key.trim())) {
318
+ throw new TypeError("A signal declaration key must be a nonempty string.");
319
+ }
320
+ return key;
321
+ }
322
+ function __signalAt(site, initial, options) {
323
+ const explicit = signalOptionsKey(options);
324
+ site ??= explicit;
325
+ const key = descriptorKey(site, explicit);
326
+ return new SignalDescriptor(
327
+ key,
328
+ "signal",
329
+ (owner) => {
330
+ const early = readEarlySignalValue(scopeOwners.get(owner) ?? owner, {
331
+ scope: site?.startsWith("g:") ? "document" : "instance",
332
+ nodeKey: key
333
+ });
334
+ return createDeclaredSignalCell(
335
+ owner,
336
+ key,
337
+ early === void 0 ? initial : early.value,
338
+ early !== void 0
339
+ );
340
+ },
341
+ site
342
+ );
343
+ }
344
+ function signal$(initial, options) {
345
+ return __signalAt(void 0, initial, options);
346
+ }
347
+ function __derivedScalarAt(site, compute, options) {
348
+ if (typeof compute !== "function") throw new TypeError("derived$ requires a function.");
349
+ const explicit = signalOptionsKey(options);
350
+ site ??= explicit;
351
+ const key = descriptorKey(site, explicit);
352
+ return new DerivedDescriptor(
353
+ key,
354
+ "derived",
355
+ (owner) => createDeclaredScalarCell(
356
+ owner,
357
+ key,
358
+ () => runWithSignalOwner(owner, () => compute())
359
+ ),
360
+ site
361
+ );
362
+ }
363
+ function readSignalBinding(handle$) {
364
+ if (!isSignalHandle(handle$)) throw new TypeError("A signal binding requires a signal handle.");
365
+ return handle$[SIGNAL_BINDING_READ]();
366
+ }
367
+ function __startSignalReads(handles, primitive = false) {
368
+ untrack(() => {
369
+ for (const handle of handles) {
370
+ try {
371
+ const value = handle[SIGNAL_BINDING_READ]();
372
+ if (primitive && value != null && (typeof value === "object" || typeof value === "function" || typeof value === "symbol"))
373
+ break;
374
+ } catch (error) {
375
+ if (!isThenable(error)) break;
376
+ }
377
+ }
378
+ });
379
+ }
380
+ function bindStreamedSignalSelection(owner, identity) {
381
+ const scope = streamedScope(owner, identity, true);
382
+ return scope ? bindScopeStreamedSelection(scope, identity) : false;
383
+ }
384
+ function acceptStreamedSignalResult(owner, frame) {
385
+ const scope = streamedScope(owner, frame.identity, false);
386
+ return scope ? acceptScopeStreamedResult(scope, frame) : false;
387
+ }
388
+ function failStreamedSignalResult(owner, identity, code) {
389
+ const scope = streamedScope(owner, identity, false);
390
+ return scope ? failScopeStreamedResult(scope, identity, new SignalStreamError(code)) : false;
391
+ }
392
+ function receiverErrorCode(error) {
393
+ if (error && (typeof error === "object" || typeof error === "function") && typeof error.code === "string") {
394
+ return error.code;
395
+ }
396
+ return "receiver";
397
+ }
398
+ function attachStreamedSignalResult(receiver, owner, identity) {
399
+ const scope = streamedScope(owner, identity, true);
400
+ if (!(scope instanceof ScopeImpl) || !scope.bindStreamedSelection(identity))
401
+ throw new SignalStreamError("identity");
402
+ const fail = (error) => {
403
+ failStreamedSignalResult(owner, identity, receiverErrorCode(error));
404
+ };
405
+ const consumer = {
406
+ accept(frame) {
407
+ if (acceptStreamedSignalResult(owner, frame)) return;
408
+ if (scope.isStreamedSelectionPending(frame.identity)) return false;
409
+ fail(new SignalStreamError("identity"));
410
+ throw new SignalStreamError("identity");
411
+ },
412
+ retainCompleted(frames) {
413
+ return scope.retainCompletedStreamedResult(identity, frames);
414
+ },
415
+ fail
416
+ };
417
+ try {
418
+ let detach = receiver.attachResult(identity, consumer);
419
+ const stopWaiting = scope.whenStreamedSelectionReady(identity, () => {
420
+ detach = receiver.attachResult(identity, consumer);
421
+ });
422
+ return () => {
423
+ stopWaiting();
424
+ detach();
425
+ };
426
+ } catch (error) {
427
+ fail(error);
428
+ throw error;
429
+ }
430
+ }
431
+ export {
432
+ DerivedDescriptor,
433
+ Descriptor,
434
+ __derivedScalarAt,
435
+ __signalAt,
436
+ __startSignalReads,
437
+ acceptStreamedSignalResult,
438
+ attachStreamedSignalResult,
439
+ bindStreamedSignalSelection,
440
+ createSignalOwnerLifecycle,
441
+ descriptorKey,
442
+ failStreamedSignalResult,
443
+ initializeDocumentSignalOwner,
444
+ isSignalHandle2 as isSignalHandle,
445
+ isWritableSignal,
446
+ readSignalBinding,
447
+ resolveCurrentSignalHandle,
448
+ resolveSignalHandleForOwner,
449
+ resolveSignalHandleForScope,
450
+ signal$,
451
+ signalOptionsKey
452
+ };
@@ -1,16 +1,46 @@
1
+ import type { SignalCandidateFrame } from './transition-candidate.js';
1
2
  import { type ReactiveFlags as AlienReactiveFlags, type ReactiveNode } from 'alien-signals/system';
2
3
  import { NATIVE_DOM_VALUE, type NativeReadInspection, type NativeReadSource, type NativeSerializedScope } from './read-protocol.js';
3
- import type { AdoptionFrame, ConnectionState, ScopeSeed, SIGNAL_HANDLE, SignalHandle, SignalSnapshot, SignalTraceEvent } from './types.js';
4
+ import { SIGNAL_BINDING_READ, SIGNAL_BINDING_SUBSCRIBE, SIGNAL_BINDING_IDENTITY, SIGNAL_HANDLE, type AdoptionFrame, type ConnectionState, type ScopeSeed, type SignalHandle, type SignalSnapshot, type SignalTraceEvent } from './types.js';
4
5
  export interface GraphOwner {
5
6
  readonly scopeKey: string;
6
7
  readonly epoch: number;
7
8
  readonly retired: boolean;
9
+ /** Optional document freeze barrier; ordinary owners never allocate one. */
10
+ readonly readBarrier?: Promise<void> | undefined;
8
11
  readonly observers: Set<SignalObserver>;
9
12
  readonly seedable: boolean;
10
13
  beginAdoption(seed: ScopeSeed): AdoptionFrame;
11
14
  serializeRead(node: ScopedNode, read: SignalReadMode): readonly NativeSerializedScope[] | undefined;
12
15
  trace(type: SignalTraceEvent['type'], node?: ScopedNode): void;
16
+ /** Internal prototype: only explicitly supported producers may enter a candidate. */
17
+ forkCandidate?(node: ScopedNode, target: ScopedNode, frame: SignalCandidateFrame): CandidateProducer | undefined;
13
18
  }
19
+ export interface CandidateProducer {
20
+ dispose(): void;
21
+ /** Explicit async reads complement the synchronous graph edges. */
22
+ dependencies?(): Iterable<ScopedNode>;
23
+ prepare(): {
24
+ status: 'ready';
25
+ receipt: CandidateProducerReceipt;
26
+ } | {
27
+ status: 'pending';
28
+ waiting: PromiseLike<unknown>;
29
+ } | {
30
+ status: 'error';
31
+ error: unknown;
32
+ } | {
33
+ status: 'invalid';
34
+ };
35
+ }
36
+ export interface CandidateProducerReceipt {
37
+ validate(): boolean;
38
+ publish(): () => void;
39
+ /** Canonical revisions are installed; transfer leases without evaluating readers. */
40
+ accept?(): void;
41
+ }
42
+ export { CandidateUnsupportedError } from './transition-state.js';
43
+ export type { SignalCandidateFrame, CandidatePreparation } from './transition-candidate.js';
14
44
  export type SignalReadMode = 'value' | 'latest' | 'snapshot';
15
45
  declare const ReactiveFlags: {
16
46
  readonly None: 0;
@@ -39,6 +69,8 @@ export declare function setHistoricalReader(read: ((node: ScopedNode, read: Sign
39
69
  export declare function pure<T>(read: () => T): T;
40
70
  /** Untracking never relaxes the separate computation/render write guard. */
41
71
  export declare function untrack<T>(run: () => T): T;
72
+ /** Cancellation callbacks observe committed state, even during candidate evaluation. */
73
+ export declare function untrackCommitted<T>(run: () => T): T;
42
74
  export declare function startSignalBatch(): void;
43
75
  export declare function endSignalBatch(): void;
44
76
  export declare function signalBatch<T>(run: () => T): T;
@@ -50,13 +82,14 @@ export declare function readyState<T>(value: T, activity?: {
50
82
  }): NodeState<T>;
51
83
  export declare function errorState(error: unknown, connection?: ConnectionState, requestKey?: string): NodeState<never>;
52
84
  export declare function pendingState(waiting: PromiseLike<unknown>, connection?: ConnectionState, requestKey?: string, resolveWaiting?: () => void): NodeState<never>;
85
+ export declare function idleState(): NodeState<never>;
53
86
  export declare function sameState(a: NodeState | undefined, b: NodeState): boolean;
54
87
  export declare function releaseRetention(node: ScopedNode): void;
55
88
  export declare class ScopedNode<T = any> implements SignalHandle<T>, ReactiveNode {
56
89
  readonly owner: GraphOwner;
57
90
  readonly key: string;
58
91
  readonly kind: 'signal' | 'derived' | 'async';
59
- readonly [SIGNAL_HANDLE]: T;
92
+ get [SIGNAL_HANDLE](): true;
60
93
  deps: ReactiveNode['deps'];
61
94
  depsTail: ReactiveNode['depsTail'];
62
95
  subs: ReactiveNode['subs'];
@@ -64,7 +97,8 @@ export declare class ScopedNode<T = any> implements SignalHandle<T>, ReactiveNod
64
97
  flags: ReactiveFlags;
65
98
  revision: number;
66
99
  state: NodeState<T> | undefined;
67
- compute: (() => NodeState<T>) | undefined;
100
+ compute: ((target: ScopedNode<T>) => NodeState<T>) | undefined;
101
+ invalidateAttempt: (() => void) | undefined;
68
102
  last: T | undefined;
69
103
  lastState: NodeState<T> | undefined;
70
104
  hasLast: boolean;
@@ -78,6 +112,12 @@ export declare class ScopedNode<T = any> implements SignalHandle<T>, ReactiveNod
78
112
  }): void;
79
113
  constructor(owner: GraphOwner, key: string, kind: 'signal' | 'derived' | 'async');
80
114
  get(): T;
115
+ [SIGNAL_BINDING_READ](): T;
116
+ [SIGNAL_BINDING_SUBSCRIBE](notify: () => void, onRetire?: () => void): () => void;
117
+ [SIGNAL_BINDING_IDENTITY](): {
118
+ scope: "instance";
119
+ nodeKey: string;
120
+ };
81
121
  [NATIVE_DOM_VALUE](): T;
82
122
  set(value: T | ((previous: T) => T)): void;
83
123
  latest(): T | undefined;
@@ -89,12 +129,15 @@ export declare function assertAlive(owner: GraphOwner): void;
89
129
  /** Inspect only cached metadata; never refresh a dormant or invalidated node. */
90
130
  export declare function inspectNativeNode(node: ScopedNode, read: SignalReadMode): NativeReadInspection;
91
131
  export declare function readNode<T>(node: ScopedNode<T>, read?: SignalReadMode): NodeState<T>;
92
- export declare function strictValue<T>(state: NodeState<T>): T;
132
+ export declare function strictValue<T>(state: NodeState<T>, key?: string): T;
133
+ /** Track historical lease release, but keep live binding reads out of the broad collector. */
134
+ export declare function readSignalBinding<T>(handle$: SignalHandle<T>): T;
93
135
  export declare function refreshNode<T>(node: ScopedNode<T>): NodeState<T>;
94
136
  export declare function publishNode<T>(node: ScopedNode<T>, next: NodeState<T>): void;
95
137
  /** An explicit source retry invalidates even a cached description failure. */
96
138
  export declare function invalidateNode(node: ScopedNode): void;
97
139
  export declare function derivedState<T>(node: ScopedNode<T>, read: () => T): NodeState<T>;
140
+ export declare function derivedValueState<T>(node: ScopedNode<T>, value: T, activity?: Pick<SignalSnapshot<T>, 'refreshing' | 'complete' | 'connection'>, additionalDependencies?: Iterable<ScopedNode>): NodeState<T>;
98
141
  export declare class SignalObserver implements ReactiveNode {
99
142
  node: ScopedNode | undefined;
100
143
  notify: (() => void) | undefined;
@@ -105,6 +148,8 @@ export declare class SignalObserver implements ReactiveNode {
105
148
  flags: ReactiveFlags;
106
149
  constructor(node: ScopedNode | undefined, notify: (() => void) | undefined, native: boolean, previous: NodeState | undefined);
107
150
  }
151
+ export declare function attachObserver(node: ScopedNode, notify: () => void, native: boolean, state?: NodeState): () => void;
152
+ /** Internal attempt dependency subscription; callers already hold a graph lease. */
153
+ export declare function subscribeNode(node: ScopedNode, notify: () => void): () => void;
108
154
  export declare function stopObserver(observer: SignalObserver): void;
109
155
  export declare function retireGraph(owner: GraphOwner, nodes: Iterable<ScopedNode>): void;
110
- export {};