octane 0.3.1 → 0.3.2

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 (45) hide show
  1. package/dist/cjs/constants.cjs +18 -25
  2. package/dist/cjs/css.cjs +6 -0
  3. package/dist/cjs/dom-binding-protocol.cjs +37 -14
  4. package/dist/cjs/hydration/control-capture.cjs +12 -4
  5. package/dist/cjs/hydration/event-capture.cjs +6 -7
  6. package/dist/cjs/hydration-markers.cjs +40 -2
  7. package/dist/cjs/runtime-tags.cjs +55 -0
  8. package/dist/cjs/runtime.cjs +136 -113
  9. package/dist/cjs/runtime.server.cjs +34 -41
  10. package/dist/cjs/server/streamed-signals.cjs +7 -4
  11. package/dist/cjs/signals/control-binding.cjs +2 -1
  12. package/dist/cjs/stream-protocol.cjs +9 -8
  13. package/dist/cjs/version.cjs +1 -1
  14. package/dist/compiler/compile.js +70 -17
  15. package/dist/compiler/dom-bindings.js +5 -0
  16. package/dist/constants.d.ts +7 -18
  17. package/dist/constants.js +11 -9
  18. package/dist/css.d.ts +7 -0
  19. package/dist/css.js +4 -0
  20. package/dist/dom-binding-program.js +12 -5
  21. package/dist/dom-binding-protocol.d.ts +14 -1
  22. package/dist/dom-binding-protocol.js +40 -14
  23. package/dist/hydration/control-capture.d.ts +2 -0
  24. package/dist/hydration/control-capture.js +18 -5
  25. package/dist/hydration/event-capture.js +1 -2
  26. package/dist/hydration/independent-island.js +5 -5
  27. package/dist/hydration-markers.d.ts +30 -0
  28. package/dist/hydration-markers.js +27 -1
  29. package/dist/react/index.js +1 -1
  30. package/dist/react/react-compat-shared.js +5 -3
  31. package/dist/react/shared.d.ts +1 -3
  32. package/dist/react/shared.js +1 -1
  33. package/dist/runtime-tags.d.ts +34 -0
  34. package/dist/runtime-tags.js +22 -0
  35. package/dist/runtime.d.ts +5 -14
  36. package/dist/runtime.js +116 -71
  37. package/dist/runtime.server.d.ts +2 -3
  38. package/dist/runtime.server.js +25 -17
  39. package/dist/server/streamed-signals.js +7 -4
  40. package/dist/signals/control-binding.js +4 -2
  41. package/dist/stream-protocol.js +20 -9
  42. package/dist/universal-core.js +8 -4
  43. package/dist/universal-native.js +1 -1
  44. package/dist/version.js +1 -1
  45. package/package.json +3 -3
package/dist/runtime.js CHANGED
@@ -113,6 +113,7 @@ import {
113
113
  unregisterHydrationIntentBoundary,
114
114
  wasEarlyHydrationIntentHandled
115
115
  } from "./hydration/event-capture.js";
116
+ import { isRestoredHydrationTextarea } from "./hydration/control-capture.js";
116
117
  import { sanitizeURL, sanitizeURLAttribute } from "./sanitize-url.js";
117
118
  import {
118
119
  invalidHtmlNestingWithAncestor,
@@ -126,7 +127,30 @@ import {
126
127
  } from "./component-flags.js";
127
128
  import { formatClientError } from "./error-codes.client.generated.js";
128
129
  import { formAuthoringDiagnostics } from "./form-diagnostics.js";
129
- import { isBindingOpenComment } from "./dom-binding-protocol.js";
130
+ import {
131
+ bindingRootMarker,
132
+ BINDING_OPEN_PREFIX,
133
+ isBindingOpenComment,
134
+ isForBindingOpenComment
135
+ } from "./dom-binding-protocol.js";
136
+ import {
137
+ formatUseId,
138
+ HYDRATION_FOR_ARM_INDEX,
139
+ HYDRATION_FOR_PREFIX,
140
+ HYDRATE_MARKER_SELECTOR
141
+ } from "./hydration-markers.js";
142
+ import {
143
+ ACTIVITY_TAG,
144
+ CHILDREN_BLOCK_TAG as CHILDREN_BLOCK,
145
+ CONTEXT_TAG,
146
+ ELEMENT_TAG,
147
+ FRAGMENT_TAG,
148
+ LAZY_COMPONENT_TAG as LAZY_COMPONENT,
149
+ PORTAL_TAG,
150
+ REACT_CONTEXT_TAG as REACT_FOREIGN_CONTEXT_TAG,
151
+ RENDERER_REGION_OWNER_TAG as RENDERER_REGION_OWNER,
152
+ SUSPENSE_TAG
153
+ } from "./runtime-tags.js";
130
154
  import { moveNativeNodeBefore } from "./dom-focused-move.js";
131
155
  import {
132
156
  HYDRATE_STREAM_TOKEN_ATTR,
@@ -972,7 +996,6 @@ let NEXT_EFFECT_RENDER_VERSION = 1;
972
996
  const ACTIVE_WARM_PLANS = [];
973
997
  let NEXT_WARM_EPISODE = 1;
974
998
  let CURRENT_WARM_EPISODE = 0;
975
- const RENDERER_REGION_OWNER = /* @__PURE__ */ Symbol.for("octane.renderer-region.owner");
976
999
  const RENDERER_REGION_DOM_OWNERS = /* @__PURE__ */ new WeakMap();
977
1000
  let RENDERER_REGION_OWNER_COUNT = 0;
978
1001
  const RENDERER_REGION_DOM_BINDINGS = /* @__PURE__ */ new WeakMap();
@@ -2849,8 +2872,6 @@ function vtCaptureElements(block, owner) {
2849
2872
  }
2850
2873
  const VT_SCOPE_OWNERS = /* @__PURE__ */ new WeakMap();
2851
2874
  const VT_INVALID_SCOPE_WARNED = /* @__PURE__ */ new WeakSet();
2852
- const VT_SCOPE_STYLE_ID = "octane-view-transition-scope";
2853
- const VT_SCOPE_CSS = '[vt-scope="element"]{view-transition-scope:all!important}';
2854
2875
  const VT_SCOPE_STYLED_DOCUMENTS = /* @__PURE__ */ new WeakSet();
2855
2876
  function vtInjectScopeStyle(host) {
2856
2877
  if (DEFERRED_LAYOUT_DRIVER?.stageAction(() => vtInjectScopeStyle(host), true) === true) return;
@@ -8236,7 +8257,6 @@ function useEffectEvent(fn, slot) {
8236
8257
  return cell.impl.apply(void 0, args);
8237
8258
  });
8238
8259
  }
8239
- const CONTEXT_TAG = /* @__PURE__ */ Symbol.for("octane.context");
8240
8260
  // @__NO_SIDE_EFFECTS__
8241
8261
  function createContext(defaultValue) {
8242
8262
  const ctx = function ProviderBody(props, scope) {
@@ -8360,7 +8380,6 @@ function provideContext(scope, context, value) {
8360
8380
  }
8361
8381
  values.set(context, value);
8362
8382
  }
8363
- const CHILDREN_BLOCK = /* @__PURE__ */ Symbol.for("octane.childrenBlock");
8364
8383
  const CHILDREN_BODY = /* @__PURE__ */ Symbol.for("octane.childrenBody");
8365
8384
  function markSingleRoot(component) {
8366
8385
  component.$$singleRoot = true;
@@ -8513,7 +8532,6 @@ const HYDRATE_STRATEGY_TYPES = /* @__PURE__ */ new Set([
8513
8532
  "never",
8514
8533
  "dynamic"
8515
8534
  ]);
8516
- const HYDRATE_MARKER_SELECTOR = "[data-octane-hydrate-id]";
8517
8535
  const HYDRATE_STREAM_ERROR_ATTR = "data-oct-err";
8518
8536
  const HYDRATE_STREAM_BOUNDARY_SELECTOR = `template[${STREAM_BOUNDARY_ATTR}]`;
8519
8537
  const HYDRATE_STREAM_SCAN_MASK = 1 | 128;
@@ -9535,7 +9553,7 @@ const Suspense = /* @__PURE__ */ markComponentFlags(
9535
9553
  },
9536
9554
  COMPONENT_FLAG_BOUNDARY,
9537
9555
  "Suspense",
9538
- /* @__PURE__ */ Symbol.for("octane.suspense")
9556
+ SUSPENSE_TAG
9539
9557
  );
9540
9558
  function initializeViewTransitionComponent() {
9541
9559
  return markComponentFlags(
@@ -9609,7 +9627,6 @@ function use(usable) {
9609
9627
  }
9610
9628
  return useThenable(usable);
9611
9629
  }
9612
- const REACT_FOREIGN_CONTEXT_TAG = /* @__PURE__ */ Symbol.for("react.context");
9613
9630
  function useForeignContext(usable, api) {
9614
9631
  if (usable !== null && typeof usable === "object") {
9615
9632
  const bridge = rendererRegionOwnerForBlock(CURRENT_BLOCK);
@@ -10619,7 +10636,6 @@ function memoPublish(slot, value, ...deps) {
10619
10636
  function memoPublishAlways(slot, value) {
10620
10637
  return publishMemoEntry(CURRENT_SCOPE, slot, void 0, value);
10621
10638
  }
10622
- const LAZY_COMPONENT = /* @__PURE__ */ Symbol.for("octane.lazy");
10623
10639
  const LAZY_BODY_CHECK = /* @__PURE__ */ Symbol.for("octane.lazyBodyCheck");
10624
10640
  function markLazyBodyCheck(body, check) {
10625
10641
  Object.defineProperty(body, LAZY_BODY_CHECK, {
@@ -10787,7 +10803,7 @@ function useId(slot) {
10787
10803
  while (owner.limit !== void 0 && owner.next >= owner.limit && owner.overflow !== void 0) {
10788
10804
  owner = owner.overflow;
10789
10805
  }
10790
- s = { id: ":" + owner.prefix + "in-" + (owner.next++).toString(36) + ":" };
10806
+ s = { id: formatUseId(owner.prefix, owner.next++) };
10791
10807
  ensureHooks(scope).set(slot, s);
10792
10808
  }
10793
10809
  return s.id;
@@ -12083,6 +12099,8 @@ function preparePresentationSignalValue(args, frame) {
12083
12099
  runWithBlockSignalOwner(scope, () => {
12084
12100
  if (!valid()) throw new Error(formatClientError(77));
12085
12101
  const before = snapshotHydrationControl(element);
12102
+ const priorValue = readSignalBinding(handle);
12103
+ const restored = lease === void 0 ? isRestoredHydrationTextarea(element, priorValue) : !before.composing && !lease.composing() && typeof priorValue === "string" && before.value !== priorValue.replace(/\r\n?/g, "\n");
12086
12104
  const ctrl = armControlled(element);
12087
12105
  ctrl.composing = before.composing || lease?.composing() === true;
12088
12106
  if (ctrl.composing) element.addEventListener("blur", onCtrlCompositionEnd);
@@ -12104,11 +12122,15 @@ function preparePresentationSignalValue(args, frame) {
12104
12122
  if (lease !== void 0) owner.controlLeases.delete(element);
12105
12123
  if (!binding.disposed && !scope.block.disposed) {
12106
12124
  const snapshot = snapshotHydrationControl(element);
12107
- binding.value = element.value;
12108
- binding.pendingControl = snapshot.editRevision > (lease === void 0 ? 0 : before.editRevision);
12125
+ binding.value = priorValue;
12126
+ binding.pendingControl = snapshot.editRevision > (lease === void 0 ? 0 : before.editRevision) || restored;
12109
12127
  installDirectSignalControl(binding);
12110
12128
  if (!binding.pendingControl) consumeHydrationControl(element, snapshot.revision);
12111
- if (binding.pendingControl) queueDirectSignalControlAdoption(binding);
12129
+ if (binding.pendingControl)
12130
+ queueDirectSignalControlAdoption(
12131
+ binding,
12132
+ lease === void 0 ? 0 : before.editRevision
12133
+ );
12112
12134
  else {
12113
12135
  const current = readSignalBinding(handle);
12114
12136
  ctrl.sawV = true;
@@ -12252,7 +12274,7 @@ function presentationWrite(writer, kind, ...args) {
12252
12274
  return result;
12253
12275
  }
12254
12276
  function bindPresentationView(view, id) {
12255
- view[BINDING_VIEW_ROOT] = "[b;" + id + ";root";
12277
+ view[BINDING_VIEW_ROOT] = bindingRootMarker(id);
12256
12278
  return markComponentFlags(view, COMPONENT_FLAG_BOUNDARY, view.name);
12257
12279
  }
12258
12280
  const BINDING_CHILDREN_SITE = /* @__PURE__ */ Symbol.for("octane.binding.children-site");
@@ -12282,7 +12304,8 @@ function presentationStructure(writer, kind, marker, ...args) {
12282
12304
  }
12283
12305
  const range = presentationRange(frame, start, marker, kind);
12284
12306
  const expected = args[3][BINDING_VIEW_ROOT];
12285
- if (expected !== "[b;" + range.view + ";root") presentationMiss(false);
12307
+ if (range.view === void 0 || expected !== bindingRootMarker(range.view))
12308
+ presentationMiss(false);
12286
12309
  writer(...args);
12287
12310
  }
12288
12311
  function setBindingClass(element, receipt, values) {
@@ -12302,7 +12325,7 @@ function hydrationMarkerMultiplicity(data, open) {
12302
12325
  const marker = open ? HYDRATION_START : HYDRATION_END;
12303
12326
  if (data === marker) return 1;
12304
12327
  if (open && (data === HYDRATION_FOR_EMPTY || data === HYDRATION_FOR_ITEMS)) return 1;
12305
- if (open && (data.startsWith("[b;") || data.startsWith("[f")) && isBindingOpenComment(data))
12328
+ if (open && (data.startsWith(BINDING_OPEN_PREFIX) || data.startsWith(HYDRATION_FOR_PREFIX)) && isBindingOpenComment(data))
12306
12329
  return 1;
12307
12330
  if (data.length < 2 || data.charCodeAt(0) !== marker.charCodeAt(0)) return 0;
12308
12331
  const first = data.charCodeAt(1);
@@ -12364,7 +12387,7 @@ function ssrForMarkerState(node) {
12364
12387
  const data = (STAGED_DOM?.view(node) ?? node).data;
12365
12388
  if (data === HYDRATION_FOR_EMPTY) return 0;
12366
12389
  if (data === HYDRATION_FOR_ITEMS) return 1;
12367
- return isBindingOpenComment(data) && data.startsWith("[f") ? data.charCodeAt(2) === 48 ? 0 : 1 : -1;
12390
+ return isForBindingOpenComment(data) ? data.charCodeAt(HYDRATION_FOR_ARM_INDEX) === 48 ? 0 : 1 : -1;
12368
12391
  }
12369
12392
  function child(node) {
12370
12393
  if (currentHydration !== null) return (STAGED_DOM?.view(node) ?? node).firstChild;
@@ -12398,6 +12421,46 @@ function setText(node, value) {
12398
12421
  (STAGED_DOM?.view(node) ?? node).nodeValue = text;
12399
12422
  }
12400
12423
  const DIRECT_SIGNAL_BINDING = /* @__PURE__ */ Symbol("octane.direct-signal-binding");
12424
+ const CLAIMED_BINDING_VALUE = /* @__PURE__ */ Symbol("octane.claimed-binding-value");
12425
+ function hydrateClaimedBindingCaches(scope, fields) {
12426
+ if (activeHydration() === null) return;
12427
+ const bag = scope.slots[0];
12428
+ for (let i = 0; i < fields.length; i += 3) {
12429
+ const field = fields[i];
12430
+ const node = bag[fields[i + 1]];
12431
+ const element = node.nodeType === 3 ? (STAGED_DOM?.view(node) ?? node).parentNode : node;
12432
+ const claims = domBindingClaims.get(element);
12433
+ if (claims === void 0) continue;
12434
+ const channel = fields[i + 2];
12435
+ const tokenOnly = channel === "#text-token";
12436
+ let claimed = claims.has(
12437
+ tokenOnly ? "#text" : channel.startsWith("style:") ? "style:" + styleName(channel.slice(6)) : channel
12438
+ );
12439
+ if (channel === "style") {
12440
+ for (const name of claims.keys())
12441
+ if (name.startsWith("style:")) {
12442
+ claimed = true;
12443
+ break;
12444
+ }
12445
+ }
12446
+ if (!claimed) continue;
12447
+ const value = channel === "style" ? (STAGED_DOM?.view(element) ?? element).style.cssText : CLAIMED_BINDING_VALUE;
12448
+ if (typeof field === "number") {
12449
+ const slots = scope.slots[field].block.slots;
12450
+ journalRootProperty(slots, 0, slots[0]);
12451
+ slots[0] = value;
12452
+ } else {
12453
+ const cached = bag[field];
12454
+ if (cached?.[DIRECT_SIGNAL_BINDING] === true) {
12455
+ if (TRANSITION_JOURNAL !== null) journalObjectOnce(cached);
12456
+ cached.value = value;
12457
+ } else if (!tokenOnly) {
12458
+ if (TRANSITION_JOURNAL !== null) journalBag();
12459
+ bag[field] = value;
12460
+ }
12461
+ }
12462
+ }
12463
+ }
12401
12464
  function isSignalHandle(value) {
12402
12465
  return (typeof value === "object" || typeof value === "function") && value !== null && value[SIGNAL_HANDLE] === true;
12403
12466
  }
@@ -12470,7 +12533,7 @@ function writeDirectSignalBoundValue(binding, value) {
12470
12533
  const element = binding.target;
12471
12534
  const tag = element.localName;
12472
12535
  if (tag === "select") setSelectValue(element, value);
12473
- else setValue(element, value, tag === "textarea" && isWritableSignal(binding.handle));
12536
+ else setValue(element, value);
12474
12537
  }
12475
12538
  function writeDirectSignalBoundChecked(binding, value) {
12476
12539
  setChecked(binding.target, value);
@@ -12599,19 +12662,19 @@ function installDirectSignalControl(binding) {
12599
12662
  )
12600
12663
  );
12601
12664
  }
12602
- function queueDirectSignalControlAdoption(binding) {
12665
+ function queueDirectSignalControlAdoption(binding, priorEditRevision = 0) {
12603
12666
  enqueueEffectEventCommitAction(() => {
12604
12667
  if (binding.disposed || binding.scope.block.disposed || !binding.pendingControl) return;
12605
12668
  withoutSignalCandidate(
12606
12669
  () => runWithBlockSignalOwner(binding.scope, () => {
12607
12670
  const element = binding.target;
12608
12671
  const snapshot = snapshotHydrationControl(element);
12609
- if (snapshot.editRevision > 0 && isWritableSignal(binding.handle)) {
12672
+ if (isWritableSignal(binding.handle) && (snapshot.editRevision > priorEditRevision || element.localName === "textarea" && Object.is(readSignalBinding(binding.handle), binding.value))) {
12610
12673
  binding.handle.set(directSignalControlValue(binding, snapshot));
12611
12674
  }
12612
12675
  if (binding.disposed || binding.scope.block.disposed) return;
12613
12676
  if (!consumeHydrationControl(element, snapshot.revision)) {
12614
- queueDirectSignalControlAdoption(binding);
12677
+ queueDirectSignalControlAdoption(binding, priorEditRevision);
12615
12678
  return;
12616
12679
  }
12617
12680
  binding.pendingControl = false;
@@ -12645,8 +12708,9 @@ function createDirectSignalBinding(scope, target, value, site, policy, name, att
12645
12708
  };
12646
12709
  if (text !== void 0) binding.text = text;
12647
12710
  const controlSnapshot = policy.control?.snapshot(target, site) ?? null;
12648
- binding.pendingControl = activeHydration() !== null && isWritableSignal(handle) && controlSnapshot !== null && controlSnapshot.editRevision > 0;
12649
12711
  const initial = handle === null ? value : readSignalBinding(handle);
12712
+ binding.pendingControl = activeHydration() !== null && isWritableSignal(handle) && controlSnapshot !== null && (controlSnapshot.editRevision > 0 || isRestoredHydrationTextarea(target, initial));
12713
+ if (binding.pendingControl) binding.value = initial;
12650
12714
  if (!binding.pendingControl) writeDirectSignalBinding(binding, initial);
12651
12715
  if (STAGED_COMMIT_CAPTURE !== null) {
12652
12716
  DEFERRED_LAYOUT_DRIVER.stageAction(() => {
@@ -13050,10 +13114,10 @@ function applyRefValue(ref, el, prevTarget) {
13050
13114
  }
13051
13115
  ref.current = el;
13052
13116
  }
13053
- const Fragment = /* @__PURE__ */ Symbol.for("octane.Fragment");
13117
+ const Fragment = FRAGMENT_TAG;
13054
13118
  let activityDescriptorDispatch = null;
13055
13119
  function initializeActivitySentinel() {
13056
- const type = /* @__PURE__ */ Symbol.for("octane.Activity");
13120
+ const type = ACTIVITY_TAG;
13057
13121
  activityDescriptorDispatch = { type, body: renderActivityDescriptor };
13058
13122
  return type;
13059
13123
  }
@@ -13977,7 +14041,9 @@ import {
13977
14041
  devWarnStyleProperty,
13978
14042
  mergeClass,
13979
14043
  normalizeClass,
13980
- styleName
14044
+ styleName,
14045
+ VIEW_TRANSITION_SCOPE_CSS as VT_SCOPE_CSS,
14046
+ VIEW_TRANSITION_SCOPE_STYLE_ID as VT_SCOPE_STYLE_ID
13981
14047
  } from "./css.js";
13982
14048
  function setClassName(el, value) {
13983
14049
  const cls = normalizeClass(value);
@@ -14280,7 +14346,7 @@ function resolveHostPropSources(el, sources, props, readStyle) {
14280
14346
  if (readStyle !== void 0 && "style" in resolved) resolved.style = readStyle(resolved.style);
14281
14347
  return resolved;
14282
14348
  }
14283
- function setHostPropSources(el, sources, prev, scope, hasNestedChildren = false, readStyle, deferControl = false, writableTextareaValue = false) {
14349
+ function setHostPropSources(el, sources, prev, scope, hasNestedChildren = false, readStyle, deferControl = false) {
14284
14350
  const props = /* @__PURE__ */ new Map();
14285
14351
  const resolved = resolveHostPropSources(el, sources, props, readStyle);
14286
14352
  const tag = el.localName;
@@ -14295,8 +14361,7 @@ function setHostPropSources(el, sources, prev, scope, hasNestedChildren = false,
14295
14361
  props.get("defaultValue")?.value,
14296
14362
  props.get("checked")?.value,
14297
14363
  props.get("defaultChecked")?.value,
14298
- props.get("multiple")?.value,
14299
- writableTextareaValue
14364
+ props.get("multiple")?.value
14300
14365
  );
14301
14366
  return resolved;
14302
14367
  }
@@ -14317,14 +14382,12 @@ function resolveSignalStyle(value, handles, read) {
14317
14382
  }
14318
14383
  return copy ?? value;
14319
14384
  }
14320
- function resolveSignalHostPropSources(sources, readStyle, read = readSignalBinding, textarea = false) {
14385
+ function resolveSignalHostPropSources(sources, readStyle, read = readSignalBinding) {
14321
14386
  const handles = /* @__PURE__ */ new Set();
14322
14387
  let rows;
14323
- let writableTextareaValue = false;
14324
14388
  for (let i = 0; i < sources.length; i++) {
14325
14389
  const source = sources[i];
14326
14390
  if (!source[0]) {
14327
- if (textarea && source[1] === "value") writableTextareaValue = isWritableSignal(source[2]);
14328
14391
  const value = source[1] === "children" || source[1] === "style" && readStyle !== void 0 ? source[2] : source[1] === "style" ? resolveSignalStyle(source[2], handles, read) : isSignalHandle(source[2]) ? (handles.add(source[2]), read(source[2])) : source[2];
14329
14392
  if (value !== source[2]) {
14330
14393
  rows ??= sources.slice();
@@ -14337,7 +14400,6 @@ function resolveSignalHostPropSources(sources, readStyle, read = readSignalBindi
14337
14400
  let copy;
14338
14401
  for (const name of Object.keys(spread)) {
14339
14402
  const current = spread[name];
14340
- if (textarea && name === "value") writableTextareaValue = isWritableSignal(current);
14341
14403
  const value = name === "children" || name === "style" && readStyle !== void 0 ? current : name === "style" ? resolveSignalStyle(current, handles, read) : isSignalHandle(current) ? (handles.add(current), read(current)) : current;
14342
14404
  if (value !== current) {
14343
14405
  copy ??= { ...spread };
@@ -14349,7 +14411,7 @@ function resolveSignalHostPropSources(sources, readStyle, read = readSignalBindi
14349
14411
  rows[i] = [true, copy];
14350
14412
  }
14351
14413
  }
14352
- return textarea ? { sources: rows ?? sources, handles, writableTextareaValue } : { sources: rows ?? sources, handles };
14414
+ return { sources: rows ?? sources, handles };
14353
14415
  }
14354
14416
  function winningSignalHostControl(sources, name) {
14355
14417
  let winner;
@@ -14369,21 +14431,14 @@ function updateSignalHostPropSources(binding) {
14369
14431
  if (binding.disposed || binding.pendingControl || binding.scope.block.disposed) return;
14370
14432
  try {
14371
14433
  runWithBlockSignalOwner(binding.scope, () => {
14372
- const next = resolveSignalHostPropSources(
14373
- binding.sources,
14374
- binding.readStyle,
14375
- void 0,
14376
- binding.element.localName === "textarea"
14377
- );
14434
+ const next = resolveSignalHostPropSources(binding.sources, binding.readStyle);
14378
14435
  binding.resolved = setHostPropSources(
14379
14436
  binding.element,
14380
14437
  next.sources,
14381
14438
  binding.resolved,
14382
14439
  binding.scope,
14383
14440
  binding.hasNestedChildren,
14384
- binding.readStyle,
14385
- false,
14386
- next.writableTextareaValue
14441
+ binding.readStyle
14387
14442
  );
14388
14443
  if (process.env.NODE_ENV !== "production" && STAGED_DOM === null)
14389
14444
  drainDevFormDiagnostics(binding.element);
@@ -14520,22 +14575,22 @@ function disposeSignalHostPropSources(binding) {
14520
14575
  domNode(binding.element).removeEventListener("input", binding.input);
14521
14576
  queueOwnRefDetach(binding.resolved, binding.element);
14522
14577
  }
14523
- function queueSignalHostControlAdoption(binding) {
14578
+ function queueSignalHostControlAdoption(binding, priorValue) {
14524
14579
  enqueueEffectEventCommitAction(() => {
14525
14580
  if (binding.disposed || binding.scope.block.disposed || !binding.pendingControl) return;
14526
14581
  withoutSignalCandidate(
14527
14582
  () => runWithBlockSignalOwner(binding.scope, () => {
14528
14583
  const snapshot = snapshotHydrationControl(binding.element);
14529
- if (snapshot.editRevision > 0) {
14584
+ const value = winningSignalHostControl(binding.sources, "value");
14585
+ if (snapshot.editRevision > 0 || binding.element.localName === "textarea" && isWritableSignal(value) && Object.is(readSignalBinding(value), priorValue)) {
14530
14586
  const checked = winningSignalHostControl(binding.sources, "checked");
14531
- const value = winningSignalHostControl(binding.sources, "value");
14532
14587
  if (isWritableSignal(checked) && snapshot.checked !== void 0)
14533
14588
  checked.set(snapshot.checked);
14534
14589
  if (isWritableSignal(value)) value.set(snapshot.selectedValues ?? snapshot.value);
14535
14590
  }
14536
14591
  if (binding.disposed || binding.scope.block.disposed) return;
14537
14592
  if (!consumeHydrationControl(binding.element, snapshot.revision)) {
14538
- queueSignalHostControlAdoption(binding);
14593
+ queueSignalHostControlAdoption(binding, priorValue);
14539
14594
  return;
14540
14595
  }
14541
14596
  binding.pendingControl = false;
@@ -14648,14 +14703,9 @@ function bindSignalHostPropSources(scope, previous, element, sources, site, hasN
14648
14703
  const controlSnapshot = isWritableSignal(valueControl) || isWritableSignal(checkedControl) ? snapshotHydrationControl(element) : null;
14649
14704
  if (controlSnapshot !== null) {
14650
14705
  validateDirectSignalControl(element, site);
14651
- binding.pendingControl ||= activeHydration() !== null && controlSnapshot.editRevision > 0;
14706
+ binding.pendingControl ||= activeHydration() !== null && (controlSnapshot.editRevision > 0 || isWritableSignal(valueControl) && isRestoredHydrationTextarea(element, readSignalBinding(valueControl)));
14652
14707
  }
14653
- const next = resolveSignalHostPropSources(
14654
- sources,
14655
- readStyle,
14656
- void 0,
14657
- element.localName === "textarea"
14658
- );
14708
+ const next = resolveSignalHostPropSources(sources, readStyle);
14659
14709
  binding.resolved = setHostPropSources(
14660
14710
  element,
14661
14711
  next.sources,
@@ -14663,8 +14713,7 @@ function bindSignalHostPropSources(scope, previous, element, sources, site, hasN
14663
14713
  scope,
14664
14714
  hasNestedChildren,
14665
14715
  readStyle,
14666
- binding.pendingControl,
14667
- next.writableTextareaValue
14716
+ binding.pendingControl
14668
14717
  );
14669
14718
  if (STAGED_COMMIT_CAPTURE !== null) {
14670
14719
  DEFERRED_LAYOUT_DRIVER.stageAction(() => {
@@ -14686,7 +14735,7 @@ function bindSignalHostPropSources(scope, previous, element, sources, site, hasN
14686
14735
  if (!binding.pendingControl && controlSnapshot !== null)
14687
14736
  consumeHydrationControl(element, controlSnapshot.revision);
14688
14737
  }
14689
- if (binding.pendingControl) queueSignalHostControlAdoption(committed);
14738
+ if (binding.pendingControl) queueSignalHostControlAdoption(committed, binding.resolved?.value);
14690
14739
  return committed;
14691
14740
  }
14692
14741
  function isAggregatedFormControlProp(el, name) {
@@ -16332,7 +16381,7 @@ function setNativeChangeDiagnosticMetadata(el, value) {
16332
16381
  if (state !== void 0) state.staticNativeChange = false;
16333
16382
  if (value === "runtime") queueDevFormDiagnostic(el, CURRENT_SCOPE ?? void 0, true);
16334
16383
  }
16335
- function setValue(el, value, writableTextareaEcho = false) {
16384
+ function setValue(el, value) {
16336
16385
  if (CURRENT_SCOPE?.block.idState.renderOwner?.controlLeases?.has(el)) presentationMiss(false);
16337
16386
  const input = el;
16338
16387
  const ctrl = armControlled(el);
@@ -16364,17 +16413,14 @@ function setValue(el, value, writableTextareaEcho = false) {
16364
16413
  const prev = ctrl.v;
16365
16414
  ctrl.v = value;
16366
16415
  if (process.env.NODE_ENV !== "production") queueDevFormDiagnostic(el, CURRENT_SCOPE ?? void 0);
16367
- if (writableTextareaEcho) {
16368
- if ((STAGED_DOM?.view(input) ?? input).value === s) return;
16369
- if (!(ctrl.composing && Object.is(prev, value))) (STAGED_DOM?.view(input) ?? input).value = s;
16370
- if ((STAGED_DOM?.view(input) ?? input).defaultValue !== s)
16371
- (STAGED_DOM?.view(input) ?? input).defaultValue = s;
16372
- return;
16373
- }
16374
16416
  if (!(ctrl.composing && Object.is(prev, value)) && valueNeedsWrite(input, value))
16375
16417
  (STAGED_DOM?.view(input) ?? input).value = s;
16376
- if ((STAGED_DOM?.view(input) ?? input).defaultValue !== s)
16377
- (STAGED_DOM?.view(input) ?? input).defaultValue = s;
16418
+ if ((STAGED_DOM?.view(input) ?? input).defaultValue !== s) {
16419
+ const text = STAGED_DOM === null && el.localName === "textarea" ? getFirstChild(el) : null;
16420
+ if (text !== null && text.nodeType === 3 && getNextSibling(text) === null)
16421
+ domNode(text).data = s;
16422
+ else (STAGED_DOM?.view(input) ?? input).defaultValue = s;
16423
+ }
16378
16424
  }
16379
16425
  function setCheckedState(input, value, ctrl) {
16380
16426
  const first = !ctrl.sawC;
@@ -16675,7 +16721,7 @@ function setFormControlSources(el, sources) {
16675
16721
  }
16676
16722
  applyFormControlValues(el, tag, value, defaultValue, checked, defaultChecked, multiple);
16677
16723
  }
16678
- function applyFormControlValues(el, tag, value, defaultValue, checked, defaultChecked, multiple, writableTextareaValue = false) {
16724
+ function applyFormControlValues(el, tag, value, defaultValue, checked, defaultChecked, multiple) {
16679
16725
  const ctrl = armControlled(el);
16680
16726
  const first = !ctrl.formSeen;
16681
16727
  const previousMultiple = ctrl.formMultiple;
@@ -16705,7 +16751,7 @@ function applyFormControlValues(el, tag, value, defaultValue, checked, defaultCh
16705
16751
  }
16706
16752
  if (tag === "textarea") {
16707
16753
  const textarea = el;
16708
- setValue(textarea, value, writableTextareaValue);
16754
+ setValue(textarea, value);
16709
16755
  if (value == null) {
16710
16756
  if (defaultValue != null) setDefaultValue(textarea, defaultValue, first);
16711
16757
  else if (!first && (STAGED_DOM?.view(textarea) ?? textarea).defaultValue !== "")
@@ -17331,7 +17377,6 @@ function normalizePortalBody(rawBody, rawProps) {
17331
17377
  function genericPortalBody(value, scope) {
17332
17378
  childSlot(scope, 0, scope.parentNode, value, scope.endMarker);
17333
17379
  }
17334
- const PORTAL_TAG = /* @__PURE__ */ Symbol.for("octane.portal");
17335
17380
  function portalKey(value) {
17336
17381
  return typeof value === "string" || typeof value === "number" ? String(value) : null;
17337
17382
  }
@@ -17340,7 +17385,6 @@ function createPortal(body, target, props = void 0) {
17340
17385
  const key = portalKey(props);
17341
17386
  return { $$kind: PORTAL_TAG, body, target, key, props: key === null ? props : void 0 };
17342
17387
  }
17343
- const ELEMENT_TAG = /* @__PURE__ */ Symbol.for("octane.element");
17344
17388
  const KEYED_ELEMENT_DESCRIPTORS = /* @__PURE__ */ new WeakSet();
17345
17389
  function elementKeyWasProvided(descriptor) {
17346
17390
  return descriptor.key !== null || KEYED_ELEMENT_DESCRIPTORS.has(descriptor);
@@ -27978,6 +28022,7 @@ export {
27978
28022
  hostComponent,
27979
28023
  htext,
27980
28024
  htextSwap,
28025
+ hydrateClaimedBindingCaches,
27981
28026
  hydrateRoot,
27982
28027
  ifBlock,
27983
28028
  injectStyle,
@@ -1,5 +1,6 @@
1
1
  export { trustHTML, type TrustedHTML } from './trusted-html.js';
2
2
  export { readNativeDomStyle, readNativeDomProps } from './signals/read-protocol.js';
3
+ import { CONTEXT_TAG, ELEMENT_TAG, FRAGMENT_TAG } from './runtime-tags.js';
3
4
  import { EXTERNAL_HYDRATION_PROMISE, HYDRATION_RANGE_BOUNDARY } from './constants.js';
4
5
  import { type IndependentHydrateBuildRecord } from './independent-hydration-protocol.js';
5
6
  import { normalizeClass } from './css.js';
@@ -78,13 +79,12 @@ type ScopedCounts = (string | number)[] | Map<string, number>;
78
79
  export declare function ssrElement(tag: string, location: string | undefined, render: () => string, htmlIntegrationPoint?: boolean): string;
79
80
  /** Compiler ABI: validate one authored static or dynamic text child in DEV SSR. */
80
81
  export declare function ssrNestingText(value: unknown): string;
81
- declare const ELEMENT_TAG: unique symbol;
82
82
  /**
83
83
  * React-compatible Fragment sentinel. Value-position `<Fragment>` sites compile
84
84
  * to ordinary element descriptors in both modes; ssrChild recognizes this type
85
85
  * and flattens its children with the same wrapper/key rules as the client.
86
86
  */
87
- export declare const Fragment: unique symbol;
87
+ export declare const Fragment: typeof FRAGMENT_TAG;
88
88
  /**
89
89
  * React-19 `<Activity>` sentinel. Direct template sites lower to `ssrActivity`;
90
90
  * generic component and descriptor sites dispatch by this same symbol identity.
@@ -424,7 +424,6 @@ export declare const ErrorBoundary: (props: {
424
424
  fallback?: unknown;
425
425
  children?: unknown;
426
426
  }, scope: SSRScope) => string;
427
- declare const CONTEXT_TAG: unique symbol;
428
427
  export interface Context<T> {
429
428
  (props: {
430
429
  value: T;
@@ -1,7 +1,22 @@
1
1
  import { trustHTML } from "./trusted-html.js";
2
2
  import { readNativeDomStyle, readNativeDomProps } from "./signals/read-protocol.js";
3
3
  import { resolveHookPath } from "./hook-slot-cache.js";
4
- import { encodeBindingKey, isBindingOpenComment } from "./dom-binding-protocol.js";
4
+ import {
5
+ bindingRootMarker,
6
+ encodeBindingKey,
7
+ isBindingOpenComment
8
+ } from "./dom-binding-protocol.js";
9
+ import { formatUseId } from "./hydration-markers.js";
10
+ import {
11
+ ACTIVITY_TAG,
12
+ CHILDREN_BLOCK_TAG as CHILDREN_BLOCK,
13
+ CONTEXT_TAG,
14
+ ELEMENT_TAG,
15
+ FRAGMENT_TAG,
16
+ LAZY_COMPONENT_TAG as LAZY_COMPONENT,
17
+ PORTAL_TAG,
18
+ SUSPENSE_TAG
19
+ } from "./runtime-tags.js";
5
20
  import {
6
21
  BLOCK_OPEN,
7
22
  BLOCK_CLOSE,
@@ -75,7 +90,9 @@ import {
75
90
  devWarnStyleProperty,
76
91
  mergeClass,
77
92
  normalizeClass,
78
- styleName
93
+ styleName,
94
+ VIEW_TRANSITION_SCOPE_CSS,
95
+ VIEW_TRANSITION_SCOPE_STYLE_ID
79
96
  } from "./css.js";
80
97
  import {
81
98
  invalidHtmlNestingWithAncestor,
@@ -443,10 +460,8 @@ function ssrNestingText(value) {
443
460
  }
444
461
  const NOOP = () => {
445
462
  };
446
- const ELEMENT_TAG = /* @__PURE__ */ Symbol.for("octane.element");
447
- const PORTAL_TAG = /* @__PURE__ */ Symbol.for("octane.portal");
448
- const Fragment = /* @__PURE__ */ Symbol.for("octane.Fragment");
449
- const Activity = /* @__PURE__ */ Symbol.for("octane.Activity");
463
+ const Fragment = FRAGMENT_TAG;
464
+ const Activity = ACTIVITY_TAG;
450
465
  const SCOPED_ELEMENT_PROPS = /* @__PURE__ */ new WeakSet();
451
466
  const SCOPED_CHILDREN_RESOLVER = /* @__PURE__ */ Symbol("octane.scopedChildrenResolver");
452
467
  const SCOPED_VALUE_RESOLVER = /* @__PURE__ */ Symbol("octane.scopedValueResolver");
@@ -1198,7 +1213,7 @@ function ssrHtml(html) {
1198
1213
  const BINDING_HTML_ROOT = /* @__PURE__ */ Symbol.for("octane.binding.html");
1199
1214
  function ssrBindingHtml(html, id) {
1200
1215
  const output = new ServerHtml(html);
1201
- output[BINDING_HTML_ROOT] = "[b;" + id + ";root";
1216
+ output[BINDING_HTML_ROOT] = bindingRootMarker(id);
1202
1217
  return output;
1203
1218
  }
1204
1219
  function bindPresentationView(view, _id) {
@@ -3225,7 +3240,7 @@ const Suspense = /* @__PURE__ */ markComponentFlags(
3225
3240
  },
3226
3241
  COMPONENT_FLAG_BOUNDARY,
3227
3242
  "Suspense",
3228
- /* @__PURE__ */ Symbol.for("octane.suspense")
3243
+ SUSPENSE_TAG
3229
3244
  );
3230
3245
  let VT_SSR_TRY_SEQ = 0;
3231
3246
  let VT_SSR_HAS_CANDIDATES = false;
@@ -3408,11 +3423,7 @@ function vtSsrAnnotateScope(html) {
3408
3423
  true
3409
3424
  );
3410
3425
  const valid = roots === 1 && !sentinel && !text;
3411
- if (valid)
3412
- injectStyle(
3413
- "octane-view-transition-scope",
3414
- '[vt-scope="element"]{view-transition-scope:all!important}'
3415
- );
3426
+ if (valid) injectStyle(VIEW_TRANSITION_SCOPE_STYLE_ID, VIEW_TRANSITION_SCOPE_CSS);
3416
3427
  return vtSsrMapTags(
3417
3428
  html,
3418
3429
  (open) => vtSsrInject(open, [["vt-scope", valid ? "element" : "none"]]),
@@ -3604,7 +3615,6 @@ const ErrorBoundary = /* @__PURE__ */ markComponentFlags(
3604
3615
  COMPONENT_FLAG_BOUNDARY,
3605
3616
  "ErrorBoundary"
3606
3617
  );
3607
- const CONTEXT_TAG = /* @__PURE__ */ Symbol.for("octane.context");
3608
3618
  function createContext(defaultValue) {
3609
3619
  const ctx = function ProviderBody(props, scope) {
3610
3620
  return ssrHtml(renderServerContextProvider(ctx, props, scope));
@@ -4203,7 +4213,6 @@ function warmChild(comp, props) {
4203
4213
  }
4204
4214
  }
4205
4215
  let LAZY_ID = 0;
4206
- const LAZY_COMPONENT = /* @__PURE__ */ Symbol.for("octane.lazy");
4207
4216
  function resolveLazyModule(mod) {
4208
4217
  let comp = mod;
4209
4218
  if (mod != null) {
@@ -4452,7 +4461,7 @@ function useDebugValue(_value, _format) {
4452
4461
  function requestFormReset(_form) {
4453
4462
  }
4454
4463
  function useId() {
4455
- return ":" + ID_PREFIX + "in-" + (ID_COUNTER++).toString(36) + ":";
4464
+ return formatUseId(ID_PREFIX, ID_COUNTER++);
4456
4465
  }
4457
4466
  function throwOnServerEffectEventCall() {
4458
4467
  throw new Error(formatServerError(11));
@@ -4588,7 +4597,6 @@ function startTransition(fn) {
4588
4597
  function flushSync(fn) {
4589
4598
  return fn();
4590
4599
  }
4591
- const CHILDREN_BLOCK = /* @__PURE__ */ Symbol.for("octane.childrenBlock");
4592
4600
  function markChildrenBlock(fn) {
4593
4601
  if (typeof fn === "function") {
4594
4602
  fn[CHILDREN_BLOCK] = true;