octane 0.2.11 → 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 (264) 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/context-epoch.cjs +38 -0
  8. package/dist/cjs/css.cjs +6 -27
  9. package/dist/cjs/data-encoding.cjs +160 -0
  10. package/dist/cjs/dom-binding-handoff.cjs +93 -0
  11. package/dist/cjs/dom-binding-protocol.cjs +115 -0
  12. package/dist/cjs/dom-binding-styles.cjs +292 -0
  13. package/dist/cjs/dom-bindings.cjs +700 -0
  14. package/dist/cjs/dom-focused-move.cjs +66 -0
  15. package/dist/cjs/dom-stage.cjs +896 -0
  16. package/dist/cjs/dom-tables.cjs +4 -94
  17. package/dist/cjs/error-codes.client.generated.cjs +33 -0
  18. package/dist/cjs/error-codes.server.generated.cjs +24 -0
  19. package/dist/cjs/hydration/control-capture.cjs +244 -0
  20. package/dist/cjs/hydration/event-capture.cjs +125 -43
  21. package/dist/cjs/hydration/interaction-config.cjs +50 -2
  22. package/dist/cjs/hydration-markers.cjs +37 -0
  23. package/dist/cjs/independent-hydration-protocol.cjs +106 -0
  24. package/dist/cjs/index.cjs +9 -0
  25. package/dist/cjs/runtime.cjs +6397 -1683
  26. package/dist/cjs/runtime.server.cjs +1465 -213
  27. package/dist/cjs/server/early-signals.cjs +45 -0
  28. package/dist/cjs/server/index.cjs +47 -0
  29. package/dist/cjs/server/rpc-batch.cjs +149 -0
  30. package/dist/cjs/server/rpc-stream.cjs +146 -0
  31. package/dist/cjs/server/rpc.cjs +34 -15
  32. package/dist/cjs/server/signal-query-observation.cjs +158 -0
  33. package/dist/cjs/server/streamed-region.cjs +52 -0
  34. package/dist/cjs/server/streamed-signals.cjs +512 -0
  35. package/dist/cjs/server-call.cjs +103 -0
  36. package/dist/cjs/server-rpc-batch-client.cjs +141 -0
  37. package/dist/cjs/server-rpc-client.cjs +94 -27
  38. package/dist/cjs/server-rpc-protocol.cjs +141 -0
  39. package/dist/cjs/server-rpc-stream-client.cjs +118 -0
  40. package/dist/cjs/signals/actions.cjs +474 -0
  41. package/dist/cjs/signals/client.cjs +4 -1
  42. package/dist/cjs/signals/computations.cjs +460 -0
  43. package/dist/cjs/signals/control-binding.cjs +368 -0
  44. package/dist/cjs/signals/derived-facade.cjs +50 -0
  45. package/dist/cjs/signals/document-owner.cjs +71 -0
  46. package/dist/cjs/signals/early-values.cjs +155 -0
  47. package/dist/cjs/signals/encoding.cjs +6 -95
  48. package/dist/cjs/signals/engine.cjs +276 -12
  49. package/dist/cjs/signals/errors.cjs +18 -0
  50. package/dist/cjs/signals/facade.cjs +477 -0
  51. package/dist/cjs/signals/graph.cjs +166 -20
  52. package/dist/cjs/signals/handle-protocol.cjs +36 -0
  53. package/dist/cjs/signals/index.cjs +81 -2
  54. package/dist/cjs/signals/native-read-client.cjs +10 -0
  55. package/dist/cjs/signals/owner-context.cjs +112 -0
  56. package/dist/cjs/signals/query-attempt-observer.cjs +68 -0
  57. package/dist/cjs/signals/query-facade.cjs +72 -0
  58. package/dist/cjs/signals/read-protocol.cjs +54 -0
  59. package/dist/cjs/signals/requests.cjs +287 -14
  60. package/dist/cjs/signals/scalar-computations.cjs +76 -0
  61. package/dist/cjs/signals/server.cjs +4 -1
  62. package/dist/cjs/signals/transition-candidate.cjs +567 -0
  63. package/dist/cjs/signals/transition-state.cjs +106 -0
  64. package/dist/cjs/signals/types.cjs +50 -0
  65. package/dist/cjs/stream-protocol.cjs +3 -0
  66. package/dist/cjs/streamed-signals-protocol.cjs +159 -0
  67. package/dist/cjs/style-values.cjs +122 -0
  68. package/dist/cjs/trusted-html.cjs +30 -0
  69. package/dist/cjs/version.cjs +1 -1
  70. package/dist/class-names.d.ts +5 -0
  71. package/dist/class-names.js +25 -0
  72. package/dist/compiler/bundler.js +51 -22
  73. package/dist/compiler/compile.js +2534 -581
  74. package/dist/compiler/dom-binding-program.js +935 -0
  75. package/dist/compiler/dom-binding-request.js +57 -0
  76. package/dist/compiler/dom-bindings.js +2245 -0
  77. package/dist/compiler/hook-deps.js +759 -10
  78. package/dist/compiler/hydrate-boundaries.js +358 -15
  79. package/dist/compiler/index.d.ts +39 -2
  80. package/dist/compiler/index.js +1 -0
  81. package/dist/compiler/native-attribute-reads.js +127 -0
  82. package/dist/compiler/native-change-diagnostics.js +32 -38
  83. package/dist/compiler/native-read-diagnostics.js +69 -8
  84. package/dist/compiler/native-read-types.js +80 -34
  85. package/dist/compiler/parser.node.js +1 -1
  86. package/dist/compiler/renderer-boundaries.js +40 -0
  87. package/dist/compiler/server-context.js +118 -0
  88. package/dist/compiler/signal-attempt-reads.js +479 -0
  89. package/dist/compiler/signal-declarations.js +557 -0
  90. package/dist/compiler/signal-start-reads.js +413 -0
  91. package/dist/compiler/slot-hooks.d.ts +3 -1
  92. package/dist/compiler/slot-hooks.js +168 -34
  93. package/dist/compiler/strong-auto-memo.js +90 -0
  94. package/dist/compiler/strong-html.js +143 -0
  95. package/dist/compiler/strong-mode.js +764 -66
  96. package/dist/compiler/strong-template-policy.js +307 -0
  97. package/dist/compiler/template-ir.js +200 -0
  98. package/dist/compiler/typescript.d.ts +2 -0
  99. package/dist/compiler/typescript.js +2 -0
  100. package/dist/compiler/vite.d.ts +3 -1
  101. package/dist/compiler/vite.js +122 -4
  102. package/dist/compiler/volar.LICENSES.txt +1 -1
  103. package/dist/compiler/volar.d.ts +6 -1
  104. package/dist/compiler/volar.js +750 -1433
  105. package/dist/constants.d.ts +1 -0
  106. package/dist/constants.js +10 -0
  107. package/dist/context-epoch.d.ts +2 -0
  108. package/dist/context-epoch.js +13 -0
  109. package/dist/css.d.ts +2 -5
  110. package/dist/css.js +2 -23
  111. package/dist/data-encoding.d.ts +9 -0
  112. package/dist/data-encoding.js +134 -0
  113. package/dist/dom-binding-classes.d.ts +15 -0
  114. package/dist/dom-binding-classes.js +129 -0
  115. package/dist/dom-binding-controls.d.ts +2 -0
  116. package/dist/dom-binding-controls.js +6 -0
  117. package/dist/dom-binding-handoff.d.ts +55 -0
  118. package/dist/dom-binding-handoff.js +62 -0
  119. package/dist/dom-binding-program.d.ts +300 -0
  120. package/dist/dom-binding-program.js +1625 -0
  121. package/dist/dom-binding-projections.d.ts +15 -0
  122. package/dist/dom-binding-projections.js +187 -0
  123. package/dist/dom-binding-protocol.d.ts +13 -0
  124. package/dist/dom-binding-protocol.js +88 -0
  125. package/dist/dom-binding-signals.d.ts +21 -0
  126. package/dist/dom-binding-signals.js +109 -0
  127. package/dist/dom-binding-styles.d.ts +17 -0
  128. package/dist/dom-binding-styles.js +272 -0
  129. package/dist/dom-bindings.d.ts +89 -0
  130. package/dist/dom-bindings.js +670 -0
  131. package/dist/dom-focused-move.d.ts +6 -0
  132. package/dist/dom-focused-move.js +42 -0
  133. package/dist/dom-stage.d.ts +52 -0
  134. package/dist/dom-stage.js +872 -0
  135. package/dist/dom-tables.d.ts +1 -3
  136. package/dist/dom-tables.js +1 -91
  137. package/dist/error-codes.client.generated.d.ts +9 -0
  138. package/dist/error-codes.client.generated.js +33 -0
  139. package/dist/error-codes.server.generated.d.ts +6 -0
  140. package/dist/error-codes.server.generated.js +24 -0
  141. package/dist/hydration/control-capture.d.ts +62 -0
  142. package/dist/hydration/control-capture.js +223 -0
  143. package/dist/hydration/document-lifecycle.d.ts +23 -0
  144. package/dist/hydration/document-lifecycle.js +80 -0
  145. package/dist/hydration/event-capture.d.ts +20 -1
  146. package/dist/hydration/event-capture.js +128 -42
  147. package/dist/hydration/independent-island.d.ts +45 -0
  148. package/dist/hydration/independent-island.js +233 -0
  149. package/dist/hydration/index.d.ts +8 -1
  150. package/dist/hydration/index.js +55 -1
  151. package/dist/hydration/interaction-config.d.ts +5 -0
  152. package/dist/hydration/interaction-config.js +44 -1
  153. package/dist/hydration/stream-delivery.d.ts +32 -0
  154. package/dist/hydration/stream-delivery.js +333 -0
  155. package/dist/hydration/stream-receiver.d.ts +26 -0
  156. package/dist/hydration/stream-receiver.js +204 -0
  157. package/dist/hydration/stream-result-receiver.d.ts +70 -0
  158. package/dist/hydration/stream-result-receiver.js +246 -0
  159. package/dist/hydration/streamed-signals.d.ts +44 -0
  160. package/dist/hydration/streamed-signals.js +186 -0
  161. package/dist/hydration/types.d.ts +6 -0
  162. package/dist/hydration-markers.d.ts +7 -0
  163. package/dist/hydration-markers.js +10 -0
  164. package/dist/independent-hydration-protocol.d.ts +31 -0
  165. package/dist/independent-hydration-protocol.js +80 -0
  166. package/dist/index.d.ts +3 -0
  167. package/dist/index.js +6 -0
  168. package/dist/internal/signal-read.d.ts +1 -0
  169. package/dist/internal/signal-read.js +4 -0
  170. package/dist/jsx-runtime-strong.d.ts +33 -0
  171. package/dist/jsx-runtime.d.ts +58 -2
  172. package/dist/public-types.d.ts +15 -1
  173. package/dist/runtime.d.ts +297 -23
  174. package/dist/runtime.js +6405 -1679
  175. package/dist/runtime.server.d.ts +110 -27
  176. package/dist/runtime.server.js +1458 -213
  177. package/dist/server/early-signals.d.ts +14 -0
  178. package/dist/server/early-signals.js +34 -0
  179. package/dist/server/index.d.ts +11 -2
  180. package/dist/server/index.js +50 -1
  181. package/dist/server/rpc-batch.d.ts +17 -0
  182. package/dist/server/rpc-batch.js +129 -0
  183. package/dist/server/rpc-stream.d.ts +9 -0
  184. package/dist/server/rpc-stream.js +125 -0
  185. package/dist/server/rpc.d.ts +5 -1
  186. package/dist/server/rpc.js +37 -13
  187. package/dist/server/signal-query-observation.d.ts +3 -0
  188. package/dist/server/signal-query-observation.js +134 -0
  189. package/dist/server/streamed-region.d.ts +15 -0
  190. package/dist/server/streamed-region.js +30 -0
  191. package/dist/server/streamed-signals.d.ts +45 -0
  192. package/dist/server/streamed-signals.js +488 -0
  193. package/dist/server-call.d.ts +41 -0
  194. package/dist/server-call.js +75 -0
  195. package/dist/server-rpc-batch-client.d.ts +7 -0
  196. package/dist/server-rpc-batch-client.js +119 -0
  197. package/dist/server-rpc-client.d.ts +3 -1
  198. package/dist/server-rpc-client.js +99 -27
  199. package/dist/server-rpc-protocol.d.ts +47 -0
  200. package/dist/server-rpc-protocol.js +109 -0
  201. package/dist/server-rpc-stream-client.d.ts +5 -0
  202. package/dist/server-rpc-stream-client.js +98 -0
  203. package/dist/signals/actions.d.ts +12 -0
  204. package/dist/signals/actions.js +466 -0
  205. package/dist/signals/client.d.ts +2 -0
  206. package/dist/signals/client.js +1 -0
  207. package/dist/signals/computations.d.ts +37 -0
  208. package/dist/signals/computations.js +455 -0
  209. package/dist/signals/control-binding.d.ts +31 -0
  210. package/dist/signals/control-binding.js +353 -0
  211. package/dist/signals/derived-facade.d.ts +3 -0
  212. package/dist/signals/derived-facade.js +25 -0
  213. package/dist/signals/document-owner.d.ts +10 -0
  214. package/dist/signals/document-owner.js +43 -0
  215. package/dist/signals/early-values.d.ts +24 -0
  216. package/dist/signals/early-values.js +124 -0
  217. package/dist/signals/encoding.d.ts +1 -3
  218. package/dist/signals/encoding.js +3 -93
  219. package/dist/signals/engine.d.ts +53 -4
  220. package/dist/signals/engine.js +275 -16
  221. package/dist/signals/errors.d.ts +7 -0
  222. package/dist/signals/errors.js +16 -0
  223. package/dist/signals/facade.d.ts +74 -0
  224. package/dist/signals/facade.js +452 -0
  225. package/dist/signals/graph.d.ts +52 -6
  226. package/dist/signals/graph.js +174 -19
  227. package/dist/signals/handle-protocol.d.ts +4 -0
  228. package/dist/signals/handle-protocol.js +11 -0
  229. package/dist/signals/index.d.ts +12 -3
  230. package/dist/signals/index.js +71 -2
  231. package/dist/signals/native-read-client.d.ts +3 -0
  232. package/dist/signals/native-read-client.js +10 -0
  233. package/dist/signals/owner-context.d.ts +22 -0
  234. package/dist/signals/owner-context.js +77 -0
  235. package/dist/signals/query-attempt-observer.d.ts +49 -0
  236. package/dist/signals/query-attempt-observer.js +41 -0
  237. package/dist/signals/query-facade.d.ts +3 -0
  238. package/dist/signals/query-facade.js +49 -0
  239. package/dist/signals/read-protocol.d.ts +37 -2
  240. package/dist/signals/read-protocol.js +44 -0
  241. package/dist/signals/requests.d.ts +38 -5
  242. package/dist/signals/requests.js +298 -15
  243. package/dist/signals/scalar-computations.d.ts +2 -0
  244. package/dist/signals/scalar-computations.js +60 -0
  245. package/dist/signals/server.d.ts +2 -0
  246. package/dist/signals/server.js +1 -0
  247. package/dist/signals/transition-candidate.d.ts +71 -0
  248. package/dist/signals/transition-candidate.js +557 -0
  249. package/dist/signals/transition-state.d.ts +51 -0
  250. package/dist/signals/transition-state.js +70 -0
  251. package/dist/signals/types.d.ts +95 -5
  252. package/dist/signals/types.js +20 -0
  253. package/dist/stream-protocol.d.ts +0 -5
  254. package/dist/stream-protocol.js +3 -0
  255. package/dist/streamed-signals-protocol.d.ts +60 -0
  256. package/dist/streamed-signals-protocol.js +130 -0
  257. package/dist/style-values.d.ts +3 -0
  258. package/dist/style-values.js +96 -0
  259. package/dist/trusted-html.d.ts +17 -0
  260. package/dist/trusted-html.js +6 -0
  261. package/dist/universal-core.d.ts +6 -0
  262. package/dist/universal-core.js +214 -202
  263. package/dist/version.js +1 -1
  264. package/package.json +48 -5
@@ -1,7 +1,23 @@
1
1
  import {
2
+ EARLY_HYDRATION_INTENTS_KEY,
2
3
  HYDRATE_DEFAULT_INTERACTION_EVENTS,
3
- HYDRATE_INTERACTION_EVENTS_ATTR
4
+ HYDRATE_INTERACTION_EVENTS_ATTR,
5
+ HYDRATE_NATIVE_DEFAULT_INTERACTION_EVENTS,
6
+ HYDRATE_SELECTION_ATTR,
7
+ HYDRATE_SUPPORTED_INTERACTION_EVENTS
4
8
  } from "./interaction-config.js";
9
+ import { HYDRATE_INDEPENDENT_ATTR } from "../hydration-markers.js";
10
+ import { hasBindingHandoffEvent } from "../dom-binding-handoff.js";
11
+ import {
12
+ initializeHydrationControlCapture,
13
+ isEarlyHydrationIntentCurrent
14
+ } from "./control-capture.js";
15
+ import {
16
+ applyHydrationControlCandidate,
17
+ captureHydrationControlCandidate,
18
+ consumeHydrationControl,
19
+ snapshotHydrationControl
20
+ } from "./control-capture.js";
5
21
  import { HYDRATE_STREAM_TOKEN_ATTR, isRendererStreamBoundaryTemplate } from "../stream-protocol.js";
6
22
  const HYDRATE_MARKER_SELECTOR = "[data-octane-hydrate-id]";
7
23
  const HYDRATE_WHEN_ATTR = "data-octane-hydrate-when";
@@ -11,44 +27,40 @@ function isHydrationNode(target) {
11
27
  function isHydrationElement(target) {
12
28
  return isHydrationNode(target) && target.nodeType === 1;
13
29
  }
14
- const HYDRATE_SUPPORTED_INTERACTION_EVENTS = [
15
- "auxclick",
16
- "beforeinput",
17
- "click",
18
- "compositionend",
19
- "compositionstart",
20
- "compositionupdate",
21
- "contextmenu",
22
- "dblclick",
23
- "focusin",
24
- "input",
25
- "keydown",
26
- "keyup",
27
- "mousedown",
28
- "mouseenter",
29
- "mouseover",
30
- "mouseup",
31
- "pointerdown",
32
- "pointerenter",
33
- "pointerover",
34
- "pointerup",
35
- "touchend",
36
- "touchstart"
37
- ];
30
+ import { HYDRATE_SUPPORTED_INTERACTION_EVENTS as HYDRATE_SUPPORTED_INTERACTION_EVENTS2 } from "./interaction-config.js";
38
31
  function shouldPreventHydrationInteractionDefault(event) {
39
- switch (event.type) {
40
- case "beforeinput":
41
- case "compositionend":
42
- case "compositionstart":
43
- case "compositionupdate":
44
- case "input":
45
- case "mousedown":
46
- case "pointerdown":
47
- case "touchend":
48
- case "touchstart":
49
- return false;
50
- default:
51
- return event.cancelable;
32
+ return event.cancelable && !HYDRATE_NATIVE_DEFAULT_INTERACTION_EVENTS.includes(event.type);
33
+ }
34
+ let independentIntentSequences;
35
+ function advanceIndependentIntentSequence(ownerDocument) {
36
+ const sequence = (independentIntentSequences?.get(ownerDocument) ?? 0) + 1;
37
+ (independentIntentSequences ??= /* @__PURE__ */ new WeakMap()).set(ownerDocument, sequence);
38
+ return sequence;
39
+ }
40
+ function captureHydrationSelectionIntent(event, target, boundary, sequence) {
41
+ const click = event;
42
+ if (event.type !== "click" || click.button !== 0 || click.altKey || click.ctrlKey || click.metaKey || click.shiftKey)
43
+ return;
44
+ const control = target.closest(`button[${HYDRATE_SELECTION_ATTR}]`);
45
+ if (control === null || control.type !== "button" || control.closest(`[${HYDRATE_INDEPENDENT_ATTR}]`) !== boundary)
46
+ return;
47
+ const group = control.getAttribute(HYDRATE_SELECTION_ATTR);
48
+ if (!group) return;
49
+ return { control, boundary, group, sequence };
50
+ }
51
+ function isHydrationSelectionIntentCurrent(intent) {
52
+ const selection = intent.selection;
53
+ if (selection === void 0) return true;
54
+ const { control, boundary, group } = selection;
55
+ return isHydrationElement(intent.event.target) && intent.event.target.isConnected && control.isConnected && boundary.isConnected && control.contains(intent.event.target) && control.type === "button" && control.getAttribute(HYDRATE_SELECTION_ATTR) === group && intent.event.target.closest(`[${HYDRATE_INDEPENDENT_ATTR}]`) === boundary;
56
+ }
57
+ function appendHydrationReplayIntent(queue, intent) {
58
+ const selection = intent.selection;
59
+ const previous = queue[queue.length - 1];
60
+ if (selection !== void 0 && previous?.selection !== void 0 && selection.sequence === previous.selection.sequence + 1 && selection.boundary === previous.selection.boundary && selection.group === previous.selection.group && isHydrationSelectionIntentCurrent(previous)) {
61
+ queue[queue.length - 1] = intent;
62
+ } else {
63
+ queue.push(intent);
52
64
  }
53
65
  }
54
66
  const HYDRATE_BOUNDARIES = /* @__PURE__ */ new WeakMap();
@@ -56,6 +68,7 @@ const HYDRATE_PENDING_INTENTS = /* @__PURE__ */ new WeakMap();
56
68
  const HYDRATE_DELEGATED_DYNAMIC_MARKERS = /* @__PURE__ */ new WeakSet();
57
69
  const HYDRATE_HANDLED_INTENT_EVENTS = /* @__PURE__ */ new WeakSet();
58
70
  const HYDRATE_INTENT_DOCUMENTS = /* @__PURE__ */ new WeakSet();
71
+ let independentHydrationDocuments;
59
72
  function hydrationEventPathWithin(root, target) {
60
73
  if (!isHydrationNode(target)) return null;
61
74
  const streamToken = root.getAttribute(HYDRATE_STREAM_TOKEN_ATTR);
@@ -80,6 +93,9 @@ function hydrationEventPathWithin(root, target) {
80
93
  function markerStatus(marker, eventType) {
81
94
  const boundary = HYDRATE_BOUNDARIES.get(marker);
82
95
  if (boundary !== void 0) return boundary(eventType);
96
+ return hydrationMarkerInteractionStatus(marker, eventType);
97
+ }
98
+ function hydrationMarkerInteractionStatus(marker, eventType) {
83
99
  const when = marker.getAttribute(HYDRATE_WHEN_ATTR);
84
100
  if (when === null) return "hydrated";
85
101
  if (when === "never") return "never";
@@ -89,17 +105,39 @@ function markerStatus(marker, eventType) {
89
105
  const events = custom === null ? HYDRATE_DEFAULT_INTERACTION_EVENTS : custom.split(/\s+/).filter(Boolean);
90
106
  return events.includes(eventType) ? "handles" : "dormant";
91
107
  }
92
- function handleEarlyHydrationIntent(event) {
108
+ function handleEarlyHydrationIntent(event, capturedSelection) {
93
109
  const target = event.target;
94
110
  if (!isHydrationElement(target)) return;
111
+ if ((event.type === "pointerenter" || event.type === "mouseenter") && independentHydrationDocuments?.has(target.ownerDocument)) {
112
+ const boundary = target.closest(HYDRATE_MARKER_SELECTOR);
113
+ const pointer = event;
114
+ if (boundary !== null && typeof pointer.clientX === "number" && typeof pointer.clientY === "number") {
115
+ const hit = target.ownerDocument.elementFromPoint?.(pointer.clientX, pointer.clientY);
116
+ const independent2 = hit?.closest(`[${HYDRATE_INDEPENDENT_ATTR}]`);
117
+ if (independent2 && independent2 !== boundary && boundary.contains(independent2)) {
118
+ HYDRATE_HANDLED_INTENT_EVENTS.add(event);
119
+ return;
120
+ }
121
+ }
122
+ }
95
123
  const markers = [];
96
124
  let marker = target.closest(HYDRATE_MARKER_SELECTOR);
125
+ let independent = null;
97
126
  let matches = false;
98
127
  while (marker !== null) {
99
128
  markers.push(marker);
100
129
  matches ||= markerStatus(marker, event.type) === "handles";
130
+ if (marker.hasAttribute(HYDRATE_INDEPENDENT_ATTR)) {
131
+ independent = marker;
132
+ HYDRATE_HANDLED_INTENT_EVENTS.add(event);
133
+ break;
134
+ }
101
135
  marker = marker.parentElement?.closest(HYDRATE_MARKER_SELECTOR) ?? null;
102
136
  }
137
+ if (independent !== null) {
138
+ const link = target.closest("a[href],area[href]");
139
+ if (link !== null && independent.contains(link)) return;
140
+ }
103
141
  if (!matches || markers.length === 0) return;
104
142
  markers.reverse();
105
143
  let candidate = null;
@@ -122,8 +160,24 @@ function handleEarlyHydrationIntent(event) {
122
160
  }
123
161
  const path = hydrationEventPathWithin(candidate, event.target);
124
162
  if (path === null) return;
125
- const intent = { event, path };
163
+ const sequence = independent !== null && capturedSelection === void 0 ? advanceIndependentIntentSequence(target.ownerDocument) : 0;
164
+ const selection = candidate === independent ? capturedSelection === void 0 ? captureHydrationSelectionIntent(event, target, candidate, sequence) : capturedSelection : void 0;
165
+ const intent = selection ? { event, path, selection } : { event, path };
126
166
  HYDRATE_HANDLED_INTENT_EVENTS.add(event);
167
+ if (hasBindingHandoffEvent(event)) {
168
+ intent.earlyBinding = true;
169
+ const activate = () => {
170
+ if (candidateBoundary !== void 0) candidateBoundary(event.type, intent);
171
+ else {
172
+ const pending = HYDRATE_PENDING_INTENTS.get(candidate) ?? [];
173
+ appendHydrationReplayIntent(pending, intent);
174
+ HYDRATE_PENDING_INTENTS.set(candidate, pending);
175
+ }
176
+ };
177
+ if (event.isTrusted) setTimeout(activate, 0);
178
+ else queueMicrotask(activate);
179
+ return;
180
+ }
127
181
  if (event.bubbles) {
128
182
  if (shouldPreventHydrationInteractionDefault(event)) event.preventDefault();
129
183
  event.stopPropagation();
@@ -133,13 +187,22 @@ function handleEarlyHydrationIntent(event) {
133
187
  candidateBoundary(event.type, intent);
134
188
  } else {
135
189
  const pending = HYDRATE_PENDING_INTENTS.get(candidate) ?? [];
136
- pending.push(intent);
190
+ appendHydrationReplayIntent(pending, intent);
137
191
  HYDRATE_PENDING_INTENTS.set(candidate, pending);
138
192
  }
139
193
  }
140
194
  function initializeHydrationEventCapture(ownerDocument) {
141
195
  const targetDocument = ownerDocument ?? (typeof document === "undefined" ? void 0 : document);
142
196
  if (targetDocument === void 0 || HYDRATE_INTENT_DOCUMENTS.has(targetDocument)) return;
197
+ const host = targetDocument;
198
+ const mailbox = host[EARLY_HYDRATION_INTENTS_KEY];
199
+ mailbox?.stop?.();
200
+ initializeHydrationControlCapture(targetDocument);
201
+ const queued = mailbox?.q.splice(0);
202
+ host[EARLY_HYDRATION_INTENTS_KEY] = { version: 1, q: [], claimed: true };
203
+ if (mailbox?.overflow) {
204
+ throw new RangeError("Early independent Hydrate intent queue overflow; reload the document.");
205
+ }
143
206
  HYDRATE_INTENT_DOCUMENTS.add(targetDocument);
144
207
  for (let i = 0; i < HYDRATE_SUPPORTED_INTERACTION_EVENTS.length; i++) {
145
208
  targetDocument.addEventListener(
@@ -148,6 +211,21 @@ function initializeHydrationEventCapture(ownerDocument) {
148
211
  true
149
212
  );
150
213
  }
214
+ if (queued !== void 0) {
215
+ for (const entry of queued) {
216
+ const [event, , boundary, , , , control, group] = entry;
217
+ const sequence = advanceIndependentIntentSequence(targetDocument);
218
+ if (!isEarlyHydrationIntentCurrent(entry, targetDocument)) continue;
219
+ const selection = control === void 0 || group === void 0 ? null : { control, boundary, group, sequence };
220
+ if (selection !== null && !isHydrationSelectionIntentCurrent({ event, path: [], selection }))
221
+ continue;
222
+ handleEarlyHydrationIntent(event, selection);
223
+ }
224
+ }
225
+ }
226
+ function initializeIndependentHydrationEventCapture(ownerDocument) {
227
+ (independentHydrationDocuments ??= /* @__PURE__ */ new WeakSet()).add(ownerDocument);
228
+ initializeHydrationEventCapture(ownerDocument);
151
229
  }
152
230
  function registerHydrationIntentBoundary(marker, boundary) {
153
231
  HYDRATE_BOUNDARIES.set(marker, boundary);
@@ -170,12 +248,20 @@ function markDelegatedDynamicHydrationIntent(marker) {
170
248
  HYDRATE_DELEGATED_DYNAMIC_MARKERS.add(marker);
171
249
  }
172
250
  export {
173
- HYDRATE_SUPPORTED_INTERACTION_EVENTS,
251
+ HYDRATE_SUPPORTED_INTERACTION_EVENTS2 as HYDRATE_SUPPORTED_INTERACTION_EVENTS,
252
+ appendHydrationReplayIntent,
253
+ applyHydrationControlCandidate,
254
+ captureHydrationControlCandidate,
255
+ consumeHydrationControl,
174
256
  hydrationEventPathWithin,
257
+ hydrationMarkerInteractionStatus,
175
258
  initializeHydrationEventCapture,
259
+ initializeIndependentHydrationEventCapture,
260
+ isHydrationSelectionIntentCurrent,
176
261
  markDelegatedDynamicHydrationIntent,
177
262
  registerHydrationIntentBoundary,
178
263
  shouldPreventHydrationInteractionDefault,
264
+ snapshotHydrationControl,
179
265
  takeDelegatedDynamicHydrationIntent,
180
266
  takePendingHydrationIntents,
181
267
  unregisterHydrationIntentBoundary,
@@ -0,0 +1,45 @@
1
+ import type { SignalOwner } from '../signals/types.js';
2
+ import { type IndependentHydrateManifest } from '../independent-hydration-protocol.js';
3
+ import { type HydrationReplayIntent } from './event-capture.js';
4
+ export interface IndependentHydrateActivationContext {
5
+ readonly element: Element;
6
+ readonly manifest: IndependentHydrateManifest;
7
+ readonly captures: readonly unknown[];
8
+ readonly intents: readonly HydrationReplayIntent[];
9
+ readonly signalOwner?: SignalOwner;
10
+ }
11
+ export type IndependentHydrateActivator = (context: IndependentHydrateActivationContext) => void | {
12
+ unmount(): void;
13
+ } | Promise<void | {
14
+ unmount(): void;
15
+ }>;
16
+ export interface IndependentHydrateRegistration {
17
+ readonly load: () => Promise<Record<string, unknown>>;
18
+ readonly loadStyles: (styles: readonly string[]) => void | Promise<void>;
19
+ readonly signalOwner?: SignalOwner;
20
+ readonly onError?: (error: unknown) => void;
21
+ }
22
+ export interface IndependentHydrateBootstrapOptions {
23
+ /** Executing client build authority, not a value adopted from a sidecar. */
24
+ readonly buildId?: string;
25
+ readonly loadModule: (moduleId: string) => Promise<Record<string, unknown>>;
26
+ readonly loadStyles: (styles: readonly string[]) => void | Promise<void>;
27
+ readonly signalOwner?: SignalOwner;
28
+ readonly onError?: (error: unknown) => void;
29
+ }
30
+ export interface IndependentHydrateLifecycle {
31
+ (): void;
32
+ pause(): void;
33
+ resume(): void;
34
+ }
35
+ /**
36
+ * Register one compiler/bundler-proven island with the pre-root intent capture.
37
+ * Loading this island never evaluates its lexical parent or a sibling module.
38
+ */
39
+ export declare function registerIndependentHydrationIsland(element: Element, manifest: IndependentHydrateManifest, registration: IndependentHydrateRegistration): IndependentHydrateLifecycle;
40
+ /**
41
+ * Register every inert SSR sidecar before a parent root can claim its DOM.
42
+ * Module resolution is host-owned so a bundler can map exact emitted chunk IDs
43
+ * without retaining the lexical parent module.
44
+ */
45
+ export declare function bootstrapIndependentHydration(root: ParentNode, options: IndependentHydrateBootstrapOptions): IndependentHydrateLifecycle;
@@ -0,0 +1,233 @@
1
+ import { decodeSignalValue } from "../data-encoding.js";
2
+ import {
3
+ HYDRATE_INDEPENDENT_ATTR,
4
+ INDEPENDENT_HYDRATE_MANIFEST_ATTR
5
+ } from "../hydration-markers.js";
6
+ import {
7
+ isIndependentHydrateManifest
8
+ } from "../independent-hydration-protocol.js";
9
+ import {
10
+ appendHydrationReplayIntent,
11
+ hydrationMarkerInteractionStatus,
12
+ initializeIndependentHydrationEventCapture,
13
+ isHydrationSelectionIntentCurrent,
14
+ registerHydrationIntentBoundary,
15
+ takePendingHydrationIntents,
16
+ unregisterHydrationIntentBoundary
17
+ } from "./event-capture.js";
18
+ function registerIndependentHydrationIsland(element, manifest, registration) {
19
+ if (!isIndependentHydrateManifest(manifest)) {
20
+ throw new TypeError("Invalid independent Hydrate manifest.");
21
+ }
22
+ if (element.getAttribute("data-octane-hydrate-id") !== manifest.boundaryId) {
23
+ throw new Error("Independent Hydrate boundary identity mismatch.");
24
+ }
25
+ element.setAttribute(HYDRATE_INDEPENDENT_ATTR, "");
26
+ initializeIndependentHydrationEventCapture(element.ownerDocument);
27
+ let generation = 0;
28
+ let active = false;
29
+ let hydrated = false;
30
+ let replayReady = false;
31
+ let disposed = false;
32
+ let paused = false;
33
+ let root;
34
+ const intents = takePendingHydrationIntents(element) ?? [];
35
+ const activate = () => {
36
+ if (disposed || paused || active || hydrated) return;
37
+ active = true;
38
+ const attempt = ++generation;
39
+ void Promise.resolve().then(() => {
40
+ if (!disposed && generation === attempt) return registration.loadStyles(manifest.styles);
41
+ }).then(() => {
42
+ if (!disposed && generation === attempt) return registration.load();
43
+ }).then((module) => {
44
+ if (disposed || generation !== attempt || module === void 0) return;
45
+ const candidate = module[manifest.exportName];
46
+ if (typeof candidate !== "function") {
47
+ throw new TypeError("Independent Hydrate activation export is not a function.");
48
+ }
49
+ replayReady = true;
50
+ const replays = intents.splice(0);
51
+ for (let index = replays.length - 1; index >= 0; index--) {
52
+ if (!isHydrationSelectionIntentCurrent(replays[index])) replays.splice(index, 1);
53
+ }
54
+ return candidate({
55
+ element,
56
+ manifest,
57
+ captures: manifest.captures.map((value) => decodeSignalValue(value)),
58
+ intents: replays,
59
+ ...registration.signalOwner === void 0 ? {} : { signalOwner: registration.signalOwner }
60
+ });
61
+ }).then((value) => {
62
+ if (disposed || generation !== attempt) {
63
+ if (value && typeof value === "object") value.unmount();
64
+ return;
65
+ }
66
+ if (value && typeof value === "object") root = value;
67
+ hydrated = true;
68
+ active = false;
69
+ }).catch((error) => {
70
+ if (disposed || generation !== attempt) return;
71
+ active = false;
72
+ replayReady = false;
73
+ registration.onError?.(error);
74
+ });
75
+ };
76
+ const boundary = (eventType, intent) => {
77
+ if (hydrated || replayReady) return "hydrated";
78
+ if (disposed) return "never";
79
+ const status = hydrationMarkerInteractionStatus(element, eventType);
80
+ if (status === "never") return status;
81
+ if (intent !== void 0) {
82
+ appendHydrationReplayIntent(intents, intent);
83
+ activate();
84
+ }
85
+ return status;
86
+ };
87
+ registerHydrationIntentBoundary(element, boundary);
88
+ if (intents.length !== 0) activate();
89
+ return Object.assign(
90
+ () => {
91
+ if (disposed) return;
92
+ disposed = true;
93
+ generation++;
94
+ unregisterHydrationIntentBoundary(element, boundary);
95
+ root?.unmount();
96
+ },
97
+ {
98
+ pause() {
99
+ if (disposed || paused) return;
100
+ paused = true;
101
+ if (!replayReady) {
102
+ generation++;
103
+ active = false;
104
+ }
105
+ },
106
+ resume() {
107
+ if (disposed || !paused) return;
108
+ paused = false;
109
+ if (intents.length) activate();
110
+ }
111
+ }
112
+ );
113
+ }
114
+ function bootstrapIndependentHydration(root, options) {
115
+ const cleanups = /* @__PURE__ */ new Map();
116
+ const selector = `script[type="application/json"][${INDEPENDENT_HYDRATE_MANIFEST_ATTR}]`;
117
+ const ownerDocument = root.nodeType === 9 ? root : root.ownerDocument;
118
+ initializeIndependentHydrationEventCapture(ownerDocument);
119
+ let disposed = false;
120
+ let paused = false;
121
+ const register = (sidecar, documentComplete = false) => {
122
+ if (disposed || paused || !root.contains(sidecar) || !documentComplete && !sidecar.textContent)
123
+ return;
124
+ try {
125
+ let manifest;
126
+ try {
127
+ manifest = JSON.parse(sidecar.textContent || "null");
128
+ } catch (error) {
129
+ if (!documentComplete && ownerDocument.readyState === "loading") return;
130
+ throw error;
131
+ }
132
+ if (!isIndependentHydrateManifest(manifest)) {
133
+ throw new TypeError("Invalid independent Hydrate sidecar.");
134
+ }
135
+ if (options.buildId !== void 0 && manifest.buildId !== options.buildId) {
136
+ throw new Error("Independent Hydrate build identity mismatch.");
137
+ }
138
+ const element = sidecar.parentElement;
139
+ if (element === null) throw new Error("Independent Hydrate sidecar has no boundary.");
140
+ if (cleanups.has(element))
141
+ throw new Error("Independent Hydrate boundary already registered.");
142
+ cleanups.set(
143
+ element,
144
+ registerIndependentHydrationIsland(element, manifest, {
145
+ load: () => options.loadModule(manifest.moduleId),
146
+ loadStyles: options.loadStyles,
147
+ ...options.signalOwner === void 0 ? {} : { signalOwner: options.signalOwner },
148
+ ...options.onError === void 0 ? {} : { onError: options.onError }
149
+ })
150
+ );
151
+ sidecar.remove();
152
+ } catch (error) {
153
+ options.onError?.(error);
154
+ }
155
+ };
156
+ const scan = (node) => {
157
+ if (node.nodeType !== 1) return;
158
+ const element = node;
159
+ if (element.matches(selector)) register(element);
160
+ else for (const sidecar of element.querySelectorAll(selector)) register(sidecar);
161
+ };
162
+ const observer = new (ownerDocument.defaultView?.MutationObserver ?? MutationObserver)(
163
+ (records) => {
164
+ if (disposed || paused) return;
165
+ let removedBoundary = false;
166
+ for (const record of records) {
167
+ if (record.type === "characterData") {
168
+ const parent = record.target.parentElement;
169
+ if (parent?.matches(selector)) register(parent);
170
+ continue;
171
+ }
172
+ if (record.target.nodeType === 1 && record.target.matches(selector)) {
173
+ register(record.target);
174
+ }
175
+ for (const node of record.addedNodes) scan(node);
176
+ for (const node of record.removedNodes) {
177
+ if (node.nodeType === 1 && !node.matches(selector)) removedBoundary = true;
178
+ }
179
+ }
180
+ if (removedBoundary) {
181
+ for (const [element, cleanup] of cleanups) {
182
+ if (root.contains(element)) continue;
183
+ cleanups.delete(element);
184
+ cleanup();
185
+ }
186
+ }
187
+ }
188
+ );
189
+ observer.observe(root, { childList: true, subtree: true, characterData: true });
190
+ const complete = () => {
191
+ for (const sidecar of root.querySelectorAll(selector)) register(sidecar, true);
192
+ };
193
+ if (ownerDocument.readyState === "loading") {
194
+ ownerDocument.addEventListener("DOMContentLoaded", complete, { once: true });
195
+ }
196
+ for (const sidecar of root.querySelectorAll(selector)) register(sidecar);
197
+ return Object.assign(
198
+ () => {
199
+ if (disposed) return;
200
+ disposed = true;
201
+ observer.disconnect();
202
+ ownerDocument.removeEventListener("DOMContentLoaded", complete);
203
+ for (const cleanup of cleanups.values()) cleanup();
204
+ cleanups.clear();
205
+ },
206
+ {
207
+ pause() {
208
+ if (disposed || paused) return;
209
+ paused = true;
210
+ observer.disconnect();
211
+ for (const cleanup of cleanups.values()) cleanup.pause();
212
+ },
213
+ resume() {
214
+ if (disposed || !paused) return;
215
+ paused = false;
216
+ for (const [element, cleanup] of cleanups) {
217
+ if (root.contains(element)) cleanup.resume();
218
+ else {
219
+ cleanup();
220
+ cleanups.delete(element);
221
+ }
222
+ }
223
+ observer.observe(root, { childList: true, subtree: true, characterData: true });
224
+ for (const sidecar of root.querySelectorAll(selector))
225
+ register(sidecar, ownerDocument.readyState !== "loading");
226
+ }
227
+ }
228
+ );
229
+ }
230
+ export {
231
+ bootstrapIndependentHydration,
232
+ registerIndependentHydrationIsland
233
+ };
@@ -1,6 +1,13 @@
1
1
  export { condition } from './condition.js';
2
+ export { decodeSignalValue } from '../data-encoding.js';
2
3
  export type { HydrationCondition } from './condition.js';
3
- export { initializeHydrationEventCapture } from './event-capture.js';
4
+ export { applyHydrationControlCandidate, captureHydrationControlCandidate, initializeHydrationEventCapture, type HydrationControlCandidate, type HydrationControlCandidateValue, } from './event-capture.js';
5
+ export { bootstrapIndependentHydration, registerIndependentHydrationIsland, type IndependentHydrateActivationContext, type IndependentHydrateActivator, type IndependentHydrateBootstrapOptions, type IndependentHydrateRegistration, type IndependentHydrateLifecycle, } from './independent-island.js';
6
+ export { createIndependentHydrateManifest, isIndependentHydrateManifest, serializeIndependentHydrateManifest, type IndependentHydrateBuildRecord, type IndependentHydrateCapture, type IndependentHydrateManifest, type IndependentHydrateManifestTemplate, } from '../independent-hydration-protocol.js';
7
+ export { createStreamedRegionReceiver, StreamedReceiverError, type HistoricalFrameLease, type StreamedFrameDisposition, type StreamedRegionReceiver, type StreamedRegionReceiverOptions, type StreamedRegionRegistration, type StreamedResultConsumer, } from './stream-receiver.js';
8
+ export { createStreamedResultReceiver, type StreamedResultReceiver, type StreamedResultReceiverOptions, } from './stream-result-receiver.js';
9
+ export { installStreamedRendererGlobal, readStreamedRendererResponse, STREAMED_RENDERER_RECEIVER, type StreamedRendererGlobal, type StreamedRendererDeliveryOptions, type StreamedRendererReadOptions, } from './stream-delivery.js';
10
+ export { decodeStreamedRendererFrame, encodeStreamedRendererFrameForScript, isStreamFrameIdentity, isStreamedRendererFrame, sameStreamFrameIdentity, streamFrameIdentityKey, type StreamedRegionPlacementFrame, type StreamedRendererFrame, type StreamedSignalResultFrame, type StreamFrameIdentity, } from '../streamed-signals-protocol.js';
4
11
  export { idle } from './idle.js';
5
12
  export type { IdleHydrationOptions } from './idle.js';
6
13
  export { interaction } from './interaction.js';
@@ -1,5 +1,39 @@
1
1
  import { condition } from "./condition.js";
2
- import { initializeHydrationEventCapture } from "./event-capture.js";
2
+ import { decodeSignalValue } from "../data-encoding.js";
3
+ import {
4
+ applyHydrationControlCandidate,
5
+ captureHydrationControlCandidate,
6
+ initializeHydrationEventCapture
7
+ } from "./event-capture.js";
8
+ import {
9
+ bootstrapIndependentHydration,
10
+ registerIndependentHydrationIsland
11
+ } from "./independent-island.js";
12
+ import {
13
+ createIndependentHydrateManifest,
14
+ isIndependentHydrateManifest,
15
+ serializeIndependentHydrateManifest
16
+ } from "../independent-hydration-protocol.js";
17
+ import {
18
+ createStreamedRegionReceiver,
19
+ StreamedReceiverError
20
+ } from "./stream-receiver.js";
21
+ import {
22
+ createStreamedResultReceiver
23
+ } from "./stream-result-receiver.js";
24
+ import {
25
+ installStreamedRendererGlobal,
26
+ readStreamedRendererResponse,
27
+ STREAMED_RENDERER_RECEIVER
28
+ } from "./stream-delivery.js";
29
+ import {
30
+ decodeStreamedRendererFrame,
31
+ encodeStreamedRendererFrameForScript,
32
+ isStreamFrameIdentity,
33
+ isStreamedRendererFrame,
34
+ sameStreamFrameIdentity,
35
+ streamFrameIdentityKey
36
+ } from "../streamed-signals-protocol.js";
3
37
  import { idle } from "./idle.js";
4
38
  import { interaction } from "./interaction.js";
5
39
  import { load } from "./load.js";
@@ -7,12 +41,32 @@ import { media } from "./media.js";
7
41
  import { never } from "./never.js";
8
42
  import { visible } from "./visible.js";
9
43
  export {
44
+ STREAMED_RENDERER_RECEIVER,
45
+ StreamedReceiverError,
46
+ applyHydrationControlCandidate,
47
+ bootstrapIndependentHydration,
48
+ captureHydrationControlCandidate,
10
49
  condition,
50
+ createIndependentHydrateManifest,
51
+ createStreamedRegionReceiver,
52
+ createStreamedResultReceiver,
53
+ decodeSignalValue,
54
+ decodeStreamedRendererFrame,
55
+ encodeStreamedRendererFrameForScript,
11
56
  idle,
12
57
  initializeHydrationEventCapture,
58
+ installStreamedRendererGlobal,
13
59
  interaction,
60
+ isIndependentHydrateManifest,
61
+ isStreamFrameIdentity,
62
+ isStreamedRendererFrame,
14
63
  load,
15
64
  media,
16
65
  never,
66
+ readStreamedRendererResponse,
67
+ registerIndependentHydrationIsland,
68
+ sameStreamFrameIdentity,
69
+ serializeIndependentHydrateManifest,
70
+ streamFrameIdentityKey,
17
71
  visible
18
72
  };
@@ -1,2 +1,7 @@
1
1
  export declare const HYDRATE_INTERACTION_EVENTS_ATTR = "data-octane-hydrate-interaction-events";
2
+ export declare const HYDRATE_SELECTION_ATTR = "data-octane-hydrate-selection";
3
+ export declare const EARLY_HYDRATION_INTENTS_KEY = "__octaneEarlyHydrationIntents";
4
+ export declare const EARLY_HYDRATION_INTENTS_LIMIT = 256;
5
+ export declare const HYDRATE_SUPPORTED_INTERACTION_EVENTS: readonly ["auxclick", "beforeinput", "click", "compositionend", "compositionstart", "compositionupdate", "contextmenu", "dblclick", "focusin", "input", "keydown", "keyup", "mousedown", "mouseenter", "mouseover", "mouseup", "pointerdown", "pointerenter", "pointerover", "pointerup", "touchend", "touchstart"];
6
+ export declare const HYDRATE_NATIVE_DEFAULT_INTERACTION_EVENTS: readonly string[];
2
7
  export declare const HYDRATE_DEFAULT_INTERACTION_EVENTS: readonly ["pointerenter", "focusin", "pointerdown", "touchstart", "touchend", "beforeinput", "input", "compositionstart", "compositionupdate", "compositionend", "click"];