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
@@ -97,6 +97,7 @@ export declare const HYDRATE_ID_COUNT_ATTR = "data-octane-hydrate-id-count";
97
97
  export { HYDRATE_STREAM_TOKEN_ATTR } from './stream-protocol.js';
98
98
  /** Direct-child JSON script carrying this boundary's `use()` seed slice. */
99
99
  export declare const HYDRATE_SEED_ATTR = "data-octane-hydrate-seed";
100
+ export { INDEPENDENT_HYDRATE_MANIFEST_ATTR, HYDRATE_INDEPENDENT_ATTR, HYDRATE_INPUT_ATTR, SIGNAL_CONTROL_ATTR, } from './hydration-markers.js';
100
101
  /** Sentinel <template> attribute marking a pending streamed boundary. */
101
102
  export { STREAM_BOUNDARY_ATTR } from './stream-protocol.js';
102
103
  /** Hidden segment container attribute carrying a completed boundary's content. */
package/dist/constants.js CHANGED
@@ -28,6 +28,12 @@ const HYDRATE_WHEN_ATTR = "data-octane-hydrate-when";
28
28
  const HYDRATE_ID_COUNT_ATTR = "data-octane-hydrate-id-count";
29
29
  import { HYDRATE_STREAM_TOKEN_ATTR } from "./stream-protocol.js";
30
30
  const HYDRATE_SEED_ATTR = "data-octane-hydrate-seed";
31
+ import {
32
+ INDEPENDENT_HYDRATE_MANIFEST_ATTR,
33
+ HYDRATE_INDEPENDENT_ATTR,
34
+ HYDRATE_INPUT_ATTR,
35
+ SIGNAL_CONTROL_ATTR
36
+ } from "./hydration-markers.js";
31
37
  import { STREAM_BOUNDARY_ATTR } from "./stream-protocol.js";
32
38
  const STREAM_SEGMENT_ATTR = "data-oct-s";
33
39
  const STREAM_SEED_ATTR = "data-oct-seed";
@@ -66,6 +72,8 @@ export {
66
72
  FOR_BLOCK_OPEN_ITEMS,
67
73
  HYDRATE_ID_ATTR,
68
74
  HYDRATE_ID_COUNT_ATTR,
75
+ HYDRATE_INDEPENDENT_ATTR,
76
+ HYDRATE_INPUT_ATTR,
69
77
  HYDRATE_SEED_ATTR,
70
78
  HYDRATE_STATIC_END,
71
79
  HYDRATE_STATIC_ID_COUNT_PREFIX,
@@ -77,9 +85,11 @@ export {
77
85
  HYDRATION_RANGE_BOUNDARY,
78
86
  HYDRATION_START,
79
87
  HYDRATION_TEXT_SEP,
88
+ INDEPENDENT_HYDRATE_MANIFEST_ATTR,
80
89
  MUST_USE_PROPERTY_PROPS,
81
90
  POSITIVE_NUMERIC_ATTR_PROPS,
82
91
  REJECTION_SENTINEL_KEY,
92
+ SIGNAL_CONTROL_ATTR,
83
93
  STREAM_BOUNDARY_ATTR,
84
94
  STREAM_RESOURCE_ATTR,
85
95
  STREAM_SCRIPT_ATTR,
package/dist/css.d.ts CHANGED
@@ -1,8 +1,5 @@
1
- /**
2
- * clsx-style class composition (strings, numbers, arrays, objects, nesting;
3
- * falsy drops out). Octane's `class`/`className` semantics at every apply site.
4
- */
5
- export declare function normalizeClass(value: unknown): string;
1
+ import { normalizeClass } from './class-names.js';
2
+ export { normalizeClass };
6
3
  /**
7
4
  * Append a later class source onto an earlier one. Used when a synthesized
8
5
  * scope hash must share the element with a spread's class instead of replacing
package/dist/css.js CHANGED
@@ -1,25 +1,4 @@
1
- function normalizeClass(value) {
2
- if (typeof value === "string") return value;
3
- if (typeof value !== "object") {
4
- return typeof value === "number" && value ? "" + value : "";
5
- }
6
- if (value === null) return "";
7
- let str = "";
8
- if (Array.isArray(value)) {
9
- for (let i = 0; i < value.length; i++) {
10
- const item = value[i];
11
- if (item) {
12
- const inner = normalizeClass(item);
13
- if (inner) str = str ? str + " " + inner : inner;
14
- }
15
- }
16
- } else {
17
- for (const k in value) {
18
- if (value[k]) str = str ? str + " " + k : k;
19
- }
20
- }
21
- return str;
22
- }
1
+ import { normalizeClass } from "./class-names.js";
23
2
  function mergeClass(left, right) {
24
3
  const a = normalizeClass(left);
25
4
  const b = normalizeClass(right);
@@ -27,7 +6,7 @@ function mergeClass(left, right) {
27
6
  if (!b) return a;
28
7
  return a + " " + b;
29
8
  }
30
- import { hyphenateStyleName } from "./dom-tables.js";
9
+ import { hyphenateStyleName } from "./style-values.js";
31
10
  const styleNameCache = /* @__PURE__ */ new Map();
32
11
  function styleName(name) {
33
12
  const cached = styleNameCache.get(name);
@@ -0,0 +1,9 @@
1
+ import type { EncodedSignalValue } from './signals/types.js';
2
+ export declare function encodeSignalValue(value: unknown, ancestors?: Set<object>): EncodedSignalValue;
3
+ /**
4
+ * Take an immutable plain-data snapshot without an encode/decode round trip.
5
+ * Keep this traversal separate so encode-only consumers retain neither its code
6
+ * nor a per-value mode branch. Both paths enforce the same input descriptor rules.
7
+ */
8
+ export declare function snapshotSignalValue(value: unknown, ancestors?: Set<object>): unknown;
9
+ export declare function decodeSignalValue(encoded: EncodedSignalValue): unknown;
@@ -0,0 +1,134 @@
1
+ import { SignalSerializationError } from "./signals/errors.js";
2
+ function unsupported() {
3
+ throw new SignalSerializationError(
4
+ "Signal request arguments and seeds require acyclic plain data: undefined, null, booleans, finite numbers, strings, dense arrays, and plain objects with enumerable string data properties."
5
+ );
6
+ }
7
+ function encodeSignalValue(value, ancestors = /* @__PURE__ */ new Set()) {
8
+ if (value === void 0) return ["undefined"];
9
+ if (value === null) return ["null"];
10
+ if (typeof value === "boolean") return ["boolean", value];
11
+ if (typeof value === "string") return ["string", value];
12
+ if (typeof value === "number") {
13
+ if (!Number.isFinite(value)) return unsupported();
14
+ return ["number", Object.is(value, -0) ? "-0" : value];
15
+ }
16
+ if (typeof value !== "object" || ancestors.has(value)) return unsupported();
17
+ const prototype = Object.getPrototypeOf(value);
18
+ if (!Array.isArray(value) && prototype !== Object.prototype && prototype !== null) {
19
+ return unsupported();
20
+ }
21
+ ancestors.add(value);
22
+ try {
23
+ if (Array.isArray(value)) {
24
+ const keys2 = Reflect.ownKeys(value);
25
+ if (keys2.length !== value.length + 1) return unsupported();
26
+ const items = [];
27
+ for (let i = 0; i < value.length; i++) {
28
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(i));
29
+ if (!descriptor || !descriptor.enumerable || !("value" in descriptor)) return unsupported();
30
+ items.push(encodeSignalValue(descriptor.value, ancestors));
31
+ }
32
+ return ["array", items];
33
+ }
34
+ const keys = Reflect.ownKeys(value);
35
+ if (keys.some((key) => typeof key !== "string")) return unsupported();
36
+ const entries = [];
37
+ for (const key of keys.sort()) {
38
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
39
+ if (!descriptor.enumerable || !("value" in descriptor)) return unsupported();
40
+ entries.push([key, encodeSignalValue(descriptor.value, ancestors)]);
41
+ }
42
+ return ["object", entries];
43
+ } finally {
44
+ ancestors.delete(value);
45
+ }
46
+ }
47
+ function snapshotSignalValue(value, ancestors = /* @__PURE__ */ new Set()) {
48
+ if (value === void 0 || value === null || typeof value === "boolean" || typeof value === "string")
49
+ return value;
50
+ if (typeof value === "number") return Number.isFinite(value) ? value : unsupported();
51
+ if (typeof value !== "object" || ancestors.has(value)) return unsupported();
52
+ const prototype = Object.getPrototypeOf(value);
53
+ if (!Array.isArray(value) && prototype !== Object.prototype && prototype !== null) {
54
+ return unsupported();
55
+ }
56
+ ancestors.add(value);
57
+ try {
58
+ const keys = Reflect.ownKeys(value);
59
+ if (Array.isArray(value)) {
60
+ if (keys.length !== value.length + 1) return unsupported();
61
+ const items = [];
62
+ for (let i = 0; i < value.length; i++) {
63
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(i));
64
+ if (!descriptor || !descriptor.enumerable || !("value" in descriptor)) return unsupported();
65
+ items.push(snapshotSignalValue(descriptor.value, ancestors));
66
+ }
67
+ return Object.freeze(items);
68
+ }
69
+ if (keys.some((key) => typeof key !== "string")) return unsupported();
70
+ const object = {};
71
+ for (const key of keys.sort()) {
72
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
73
+ if (!descriptor.enumerable || !("value" in descriptor)) return unsupported();
74
+ Object.defineProperty(object, key, {
75
+ value: snapshotSignalValue(descriptor.value, ancestors),
76
+ enumerable: true
77
+ });
78
+ }
79
+ return Object.freeze(object);
80
+ } finally {
81
+ ancestors.delete(value);
82
+ }
83
+ }
84
+ function decodeSignalValue(encoded) {
85
+ if (!Array.isArray(encoded)) return unsupported();
86
+ const [tag, value] = encoded;
87
+ switch (tag) {
88
+ case "undefined":
89
+ if (encoded.length !== 1) return unsupported();
90
+ return void 0;
91
+ case "null":
92
+ if (encoded.length !== 1) return unsupported();
93
+ return null;
94
+ case "boolean":
95
+ if (encoded.length !== 2 || typeof value !== "boolean") return unsupported();
96
+ return value;
97
+ case "number":
98
+ if (encoded.length !== 2) return unsupported();
99
+ if (value === "-0") return -0;
100
+ if (typeof value !== "number" || !Number.isFinite(value) || Object.is(value, -0)) {
101
+ return unsupported();
102
+ }
103
+ return value;
104
+ case "string":
105
+ if (encoded.length !== 2 || typeof value !== "string") return unsupported();
106
+ return value;
107
+ case "array":
108
+ if (encoded.length !== 2 || !Array.isArray(value)) return unsupported();
109
+ return Object.freeze(value.map((item) => decodeSignalValue(item)));
110
+ case "object": {
111
+ if (encoded.length !== 2 || !Array.isArray(value)) return unsupported();
112
+ const object = {};
113
+ let previous;
114
+ for (const entry of value) {
115
+ if (!Array.isArray(entry) || entry.length !== 2 || typeof entry[0] !== "string" || previous !== void 0 && entry[0] <= previous) {
116
+ return unsupported();
117
+ }
118
+ previous = entry[0];
119
+ Object.defineProperty(object, entry[0], {
120
+ value: decodeSignalValue(entry[1]),
121
+ enumerable: true
122
+ });
123
+ }
124
+ return Object.freeze(object);
125
+ }
126
+ default:
127
+ return unsupported();
128
+ }
129
+ }
130
+ export {
131
+ decodeSignalValue,
132
+ encodeSignalValue,
133
+ snapshotSignalValue
134
+ };
@@ -0,0 +1,15 @@
1
+ export interface BindingClassGroup {
2
+ /** Preparation can be discarded without changing the DOM or its receipts. */
3
+ prepare(value: string): {
4
+ commit(): void;
5
+ };
6
+ /** An uncommitted adoption leaves the historical SSR contribution intact. */
7
+ dispose(preservePresentation?: boolean): void;
8
+ }
9
+ export declare function __bindingClassReceipt(baseline: unknown, groups: readonly unknown[]): string;
10
+ /**
11
+ * Adopt the server's historical contribution, not a possibly newer client value.
12
+ * Baseline and sibling groups each retain their own contribution to shared atoms.
13
+ * The surrounding binding runtime owns channel exclusion and subscription lifetime.
14
+ */
15
+ export declare function createBindingClassGroup(node: Element, name: string, index: number, initialReceipt?: string): BindingClassGroup;
@@ -0,0 +1,129 @@
1
+ import { normalizeClass } from "./class-names.js";
2
+ const receipts = /* @__PURE__ */ new WeakMap();
3
+ function tokens(value) {
4
+ return new Set(value.match(/[^\t\n\f\r ]+/g));
5
+ }
6
+ function __bindingClassReceipt(baseline, groups) {
7
+ return JSON.stringify([normalizeClass(baseline), groups.map(normalizeClass)]);
8
+ }
9
+ function readReceipt(node, name, initialReceipt) {
10
+ let value;
11
+ try {
12
+ value = JSON.parse(initialReceipt ?? node.getAttribute(name) ?? "null");
13
+ } catch {
14
+ throw new Error("DOM class groups require a valid compiler-issued class receipt.");
15
+ }
16
+ if (!name.startsWith("data-octane-class-") || !Array.isArray(value) || value.length !== 2 || typeof value[0] !== "string" || !Array.isArray(value[1]) || value[1].some((group) => typeof group !== "string"))
17
+ throw new Error("DOM class groups require a valid compiler-issued class receipt.");
18
+ const counts = /* @__PURE__ */ new Map();
19
+ for (const contribution of [value[0], ...value[1]])
20
+ for (const token of tokens(contribution)) counts.set(token, (counts.get(token) ?? 0) + 1);
21
+ return { name, baseline: value[0], values: value[1], counts, active: /* @__PURE__ */ new Set() };
22
+ }
23
+ function createBindingClassGroup(node, name, index, initialReceipt) {
24
+ let receipt = receipts.get(node);
25
+ if (receipt !== void 0 && receipt.name !== name)
26
+ throw new Error("A DOM host cannot mix class groups from different binding views.");
27
+ receipt ??= readReceipt(node, name, initialReceipt);
28
+ if (!Number.isInteger(index) || index < 0 || index >= receipt.values.length)
29
+ throw new Error("A DOM class group does not match its compiler-issued receipt.");
30
+ if (receipt.active.has(index)) throw new Error("This DOM class group already has a binding.");
31
+ receipt.active.add(index);
32
+ receipts.set(node, receipt);
33
+ let disposed = false;
34
+ let committed = false;
35
+ let revision = 0;
36
+ let retiring = /* @__PURE__ */ new Set();
37
+ const state = receipt;
38
+ function publish(value, next) {
39
+ const old = tokens(state.values[index]);
40
+ const remove = [];
41
+ const add = [];
42
+ for (const token of old) {
43
+ if (next.has(token)) continue;
44
+ const count = state.counts.get(token) - 1;
45
+ if (count === 0) {
46
+ state.counts.delete(token);
47
+ remove.push(token);
48
+ } else state.counts.set(token, count);
49
+ }
50
+ for (const token of next) {
51
+ if (old.has(token)) continue;
52
+ const count = state.counts.get(token) ?? 0;
53
+ state.counts.set(token, count + 1);
54
+ if (count === 0) add.push(token);
55
+ }
56
+ state.values[index] = value;
57
+ revision++;
58
+ retiring = new Set(remove);
59
+ for (const token of remove) {
60
+ node.classList.remove(token);
61
+ retiring.delete(token);
62
+ if (disposed) return;
63
+ }
64
+ for (const token of add) {
65
+ node.classList.add(token);
66
+ if (disposed) return;
67
+ }
68
+ node.setAttribute(name, JSON.stringify([state.baseline, state.values]));
69
+ }
70
+ return {
71
+ prepare(value) {
72
+ if (disposed) throw new Error("Cannot prepare a disposed DOM class group.");
73
+ const preparedAt = revision;
74
+ const next = value === state.values[index] ? null : tokens(value);
75
+ return {
76
+ commit() {
77
+ if (disposed) return;
78
+ if (preparedAt !== revision)
79
+ throw new Error("Cannot commit an outdated DOM class group preparation.");
80
+ committed = true;
81
+ if (next !== null) publish(value, next);
82
+ }
83
+ };
84
+ },
85
+ dispose(preservePresentation) {
86
+ if (disposed) return;
87
+ disposed = true;
88
+ if (!committed || preservePresentation) {
89
+ state.active.delete(index);
90
+ if (state.active.size === 0) receipts.delete(node);
91
+ return;
92
+ }
93
+ const old = tokens(state.values[index]);
94
+ state.values[index] = "";
95
+ revision++;
96
+ const remove = /* @__PURE__ */ new Set();
97
+ for (const token of old) {
98
+ const count = state.counts.get(token) - 1;
99
+ if (count === 0) {
100
+ state.counts.delete(token);
101
+ remove.add(token);
102
+ } else state.counts.set(token, count);
103
+ }
104
+ for (const token of retiring) if (!state.counts.has(token)) remove.add(token);
105
+ retiring.clear();
106
+ let failed = false;
107
+ let failure;
108
+ const attempt = (write) => {
109
+ try {
110
+ write();
111
+ } catch (error) {
112
+ if (!failed) {
113
+ failed = true;
114
+ failure = error;
115
+ }
116
+ }
117
+ };
118
+ for (const token of remove) attempt(() => node.classList.remove(token));
119
+ attempt(() => node.setAttribute(name, JSON.stringify([state.baseline, state.values])));
120
+ state.active.delete(index);
121
+ if (state.active.size === 0) receipts.delete(node);
122
+ if (failed) throw failure;
123
+ }
124
+ };
125
+ }
126
+ export {
127
+ __bindingClassReceipt,
128
+ createBindingClassGroup
129
+ };
@@ -0,0 +1,2 @@
1
+ /** Optional compiler-selected bridge to the canonical native control adapter. */
2
+ export { __createBindingControls, type BindingControlLease, type BindingControlPrepared, } from './signals/control-binding.js';
@@ -0,0 +1,6 @@
1
+ import {
2
+ __createBindingControls
3
+ } from "./signals/control-binding.js";
4
+ export {
5
+ __createBindingControls
6
+ };
@@ -0,0 +1,55 @@
1
+ /** Renderer-independent capability carried by an adopted, compiler-proven view. */
2
+ export declare const BINDING_HANDOFF: unique symbol;
3
+ /** Current early-owned range, not a license to render a different shape. */
4
+ export interface BindingHandoffRange {
5
+ readonly kind: 'if' | 'view' | 'slot' | 'text';
6
+ readonly end: Node;
7
+ readonly arm?: number;
8
+ readonly view?: string;
9
+ readonly slot?: string;
10
+ }
11
+ /** A closed caller shape proven for this actual child range, never for its module globally. */
12
+ export interface BindingHandoffView {
13
+ readonly id: string;
14
+ readonly closedProps: readonly string[];
15
+ }
16
+ export interface BindingHandoffRest {
17
+ readonly id: string;
18
+ readonly node: number;
19
+ readonly spread: number;
20
+ readonly keys: readonly string[];
21
+ }
22
+ export interface BindingHandoff {
23
+ readonly id: string;
24
+ readonly root: Node;
25
+ readonly anchor: Node;
26
+ readonly end?: Node;
27
+ /** Allocated only for a claimed structural presentation. -1 means publication is in progress. */
28
+ revision?(): number;
29
+ ranges?(): ReadonlyMap<Node, BindingHandoffRange>;
30
+ view?(root: Node): BindingHandoffView | undefined;
31
+ rest?(element: Element, site: number): BindingHandoffRest | undefined;
32
+ valid?(): boolean;
33
+ /** One deferred retry; only structural leases allocate publication listeners. */
34
+ afterPublication?(callback: () => void): () => void;
35
+ active(): boolean;
36
+ retire(publish?: () => void): void;
37
+ owner?: object;
38
+ }
39
+ export interface BindingHandoffCapability {
40
+ [BINDING_HANDOFF](): BindingHandoff;
41
+ }
42
+ /** @internal Reuse the adapter's native listener lifetime; no renderer dependency. */
43
+ export declare function registerBindingEvent(node: Node, type: string): () => void;
44
+ /** @internal Called only by a host explicitly acquiring bindingLeases. */
45
+ export declare function claimBindingHandoff(lease: BindingHandoff, owner: object): void;
46
+ /** @internal Releasing a pending claim does not dispose the early presentation. */
47
+ export declare function releaseBindingHandoff(lease: BindingHandoff): void;
48
+ /** @internal Native adapters work before the host imports its renderer. */
49
+ export declare function hasBindingHandoffEvent(event: Event): boolean;
50
+ /** @internal A synchronous takeover must not redeliver the original native command. */
51
+ export declare function markBindingEvent(event: Event, node: Node, capture: boolean): void;
52
+ /** @internal Consume only this node/phase, preserving unrelated ancestor handlers. */
53
+ export declare function consumeBindingEvent(event: Event, node: Node, capture: boolean): boolean;
54
+ /** @internal The renderer's outermost native capture observer starts each dispatch. */
55
+ export declare function beginBindingEvent(event: Event): void;
@@ -0,0 +1,62 @@
1
+ const BINDING_HANDOFF = /* @__PURE__ */ Symbol.for("octane.binding-handoff");
2
+ const events = /* @__PURE__ */ new WeakMap();
3
+ const delivered = /* @__PURE__ */ new WeakMap();
4
+ function registerBindingEvent(node, type) {
5
+ let counts = events.get(node);
6
+ if (counts === void 0) events.set(node, counts = /* @__PURE__ */ new Map());
7
+ counts.set(type, (counts.get(type) ?? 0) + 1);
8
+ return () => {
9
+ const count = counts.get(type) - 1;
10
+ if (count === 0) counts.delete(type);
11
+ else counts.set(type, count);
12
+ if (counts.size === 0) events.delete(node);
13
+ };
14
+ }
15
+ function claimBindingHandoff(lease, owner) {
16
+ if (!lease.active() || lease.owner !== void 0)
17
+ throw new Error("A DOM binding hydration lease must be active and have only one root owner.");
18
+ lease.owner = owner;
19
+ }
20
+ function releaseBindingHandoff(lease) {
21
+ lease.owner = void 0;
22
+ }
23
+ function hasBindingHandoffEvent(event) {
24
+ for (const node of event.composedPath()) {
25
+ if (events.get(node)?.has(event.type)) return true;
26
+ }
27
+ return false;
28
+ }
29
+ function markBindingEvent(event, node, capture) {
30
+ let nodes = delivered.get(event);
31
+ if (nodes === void 0) {
32
+ delivered.set(event, nodes = /* @__PURE__ */ new Map());
33
+ const cleanup = () => {
34
+ if (delivered.get(event) === nodes) delivered.delete(event);
35
+ };
36
+ if (event.isTrusted) setTimeout(cleanup, 0);
37
+ else queueMicrotask(cleanup);
38
+ }
39
+ nodes.set(node, (nodes.get(node) ?? 0) | (capture ? 2 : 1));
40
+ }
41
+ function consumeBindingEvent(event, node, capture) {
42
+ const nodes = delivered.get(event);
43
+ const flags = nodes?.get(node) ?? 0;
44
+ const bit = capture ? 2 : 1;
45
+ if ((flags & bit) === 0) return false;
46
+ if ((flags & ~bit) === 0) nodes.delete(node);
47
+ else nodes.set(node, flags & ~bit);
48
+ return true;
49
+ }
50
+ function beginBindingEvent(event) {
51
+ delivered.delete(event);
52
+ }
53
+ export {
54
+ BINDING_HANDOFF,
55
+ beginBindingEvent,
56
+ claimBindingHandoff,
57
+ consumeBindingEvent,
58
+ hasBindingHandoffEvent,
59
+ markBindingEvent,
60
+ registerBindingEvent,
61
+ releaseBindingHandoff
62
+ };