octane 0.2.13 → 0.2.15

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 (36) hide show
  1. package/dist/cjs/constants.cjs +7 -7
  2. package/dist/cjs/dom-binding-claims.cjs +28 -0
  3. package/dist/cjs/dom-binding-handoff.cjs +2 -2
  4. package/dist/cjs/dom-bindings.cjs +105 -13
  5. package/dist/cjs/runtime.cjs +311 -55
  6. package/dist/cjs/server/streamed-signals.cjs +3 -2
  7. package/dist/cjs/signals/control-binding.cjs +33 -9
  8. package/dist/cjs/signals/control-handoff.cjs +39 -0
  9. package/dist/cjs/stream-protocol.cjs +6 -0
  10. package/dist/cjs/version.cjs +1 -1
  11. package/dist/compiler/compile.js +86 -24
  12. package/dist/compiler/dom-binding-program.js +30 -3
  13. package/dist/compiler/dom-bindings.js +115 -34
  14. package/dist/compiler/volar.js +58 -17
  15. package/dist/constants.d.ts +2 -2
  16. package/dist/constants.js +2 -2
  17. package/dist/dom-binding-claims.d.ts +1 -0
  18. package/dist/dom-binding-claims.js +4 -0
  19. package/dist/dom-binding-handoff.d.ts +6 -4
  20. package/dist/dom-binding-handoff.js +1 -1
  21. package/dist/dom-binding-program.d.ts +2 -1
  22. package/dist/dom-binding-program.js +16 -1
  23. package/dist/dom-bindings.d.ts +5 -2
  24. package/dist/dom-bindings.js +105 -13
  25. package/dist/runtime.d.ts +34 -3
  26. package/dist/runtime.js +314 -55
  27. package/dist/server/streamed-signals.js +3 -2
  28. package/dist/signals/control-binding.d.ts +9 -5
  29. package/dist/signals/control-binding.js +38 -6
  30. package/dist/signals/control-handoff.d.ts +26 -0
  31. package/dist/signals/control-handoff.js +12 -0
  32. package/dist/signals/index.d.ts +1 -0
  33. package/dist/stream-protocol.d.ts +4 -0
  34. package/dist/stream-protocol.js +4 -0
  35. package/dist/version.js +1 -1
  36. package/package.json +1 -1
@@ -315,10 +315,12 @@ __export(runtime_exports, {
315
315
  });
316
316
  module.exports = __toCommonJS(runtime_exports);
317
317
  var import_hook_slot_cache = require("./hook-slot-cache.cjs");
318
+ var import_dom_binding_claims = require("./dom-binding-claims.cjs");
318
319
  var import_dom_stage = require("./dom-stage.cjs");
319
320
  var import_dom_binding_styles = require("./dom-binding-styles.cjs");
320
321
  var import_dom_binding_handoff = require("./dom-binding-handoff.cjs");
321
322
  var import_context_epoch = require("./context-epoch.cjs");
323
+ var import_control_handoff = require("./signals/control-handoff.cjs");
322
324
  var import_constants = require("./constants.cjs");
323
325
  var import_event_names = require("./event-names.cjs");
324
326
  var import_has_own = require("./has-own.cjs");
@@ -2426,7 +2428,9 @@ function rollbackRootRender(transaction) {
2426
2428
  }
2427
2429
  function retireDetachedBindingLeases(owner) {
2428
2430
  for (const lease of owner.bindingLeases) {
2429
- if (owner.bindingContainer.contains(lease.anchor)) continue;
2431
+ const preparation = lease.host !== void 0 && !lease.active() ? PRESENTATION_PREPARATIONS.get(lease) : void 0;
2432
+ if (preparation !== void 0 ? !preparation.scope.block.disposed : owner.bindingContainer.contains(lease.anchor))
2433
+ continue;
2430
2434
  owner.bindingLeases.delete(lease);
2431
2435
  PRESENTATION_PREPARATIONS.delete(lease);
2432
2436
  (0, import_dom_binding_handoff.releaseBindingHandoff)(lease);
@@ -6461,7 +6465,8 @@ function nativeEffectPublicationCurrent(entry, slot) {
6461
6465
  if (ROOT_RENDER_TRANSACTION !== null) journalObjectOnce(slot);
6462
6466
  slot.deps = void 0;
6463
6467
  slot.active = slot.connectedFn !== null;
6464
- invalidateRender(entry.scope.block, entry.scope.block);
6468
+ if (!entry.scope.block.idState.renderOwner?.disposed && !blockSubtreeDisposed(entry.scope.block))
6469
+ scheduleNativeRead(entry.scope.block);
6465
6470
  return false;
6466
6471
  }
6467
6472
  function drainMutationEffects() {
@@ -8831,6 +8836,7 @@ function releasePreservedHydrateActivation(state) {
8831
8836
  function pendingHydrateOwner(target) {
8832
8837
  let owner = null;
8833
8838
  for (let block = target; block !== null; block = block.parentBlock) {
8839
+ if (block.block !== block) continue;
8834
8840
  const state = block.slots[0];
8835
8841
  if (state?.__kind === "hydrateBlockSlot" && !state.hydrated && preservedHydrateActivations?.has(state))
8836
8842
  owner = state;
@@ -11578,7 +11584,7 @@ class HydrationCapability {
11578
11584
  const first = getFirstChild(el);
11579
11585
  if (first !== null && first.nodeType === 3) {
11580
11586
  const server = (STAGED_DOM?.view(first) ?? first).nodeValue;
11581
- if (server !== text && !isTextParserNormalizedMatch(server, text) && !isHydrationSuppressed(el)) {
11587
+ if (server !== text && import_dom_binding_claims.domBindingClaims.get(el)?.get("#text") !== server && !isTextParserNormalizedMatch(server, text) && !isHydrationSuppressed(el)) {
11582
11588
  this.recordTextMismatch(first, loc || el.__oct_loc, server);
11583
11589
  (STAGED_DOM?.view(first) ?? first).nodeValue = text;
11584
11590
  }
@@ -11663,6 +11669,7 @@ class HydrationCapability {
11663
11669
  name.indexOf(":") >= 0 ? name.slice(name.indexOf(":") + 1) : name
11664
11670
  ) : (STAGED_DOM?.view(el) ?? el).getAttribute(name);
11665
11671
  if (server === next) return false;
11672
+ if (import_dom_binding_claims.domBindingClaims.get(el)?.get(name) === server) return false;
11666
11673
  if (next !== null && isAttributeParserNormalizedMatch(server, next)) return false;
11667
11674
  const mode = hydrationMismatchMode(el);
11668
11675
  if (mode === 0) return true;
@@ -11673,10 +11680,11 @@ class HydrationCapability {
11673
11680
  }
11674
11681
  allowClass(el, next, absentIsEmpty = false) {
11675
11682
  const mode = hydrationMismatchMode(el);
11676
- if (mode === 0) return true;
11677
11683
  const rawServer = (STAGED_DOM?.view(el) ?? el).getAttribute("class");
11678
11684
  const server = absentIsEmpty && rawServer === null ? "" : rawServer;
11679
11685
  if (server === next) return true;
11686
+ if (import_dom_binding_claims.domBindingClaims.get(el)?.get("class") === rawServer) return false;
11687
+ if (mode === 0) return true;
11680
11688
  if (mode === 1) return false;
11681
11689
  if (process.env.NODE_ENV !== "production")
11682
11690
  warnHydrationValueMismatch(el.__oct_loc, "attribute `class`", server, next);
@@ -11718,6 +11726,18 @@ class HydrationCapability {
11718
11726
  applyStyleProperty(el, expectedStyle, entries[i], entry);
11719
11727
  }
11720
11728
  }
11729
+ const claims = import_dom_binding_claims.domBindingClaims.get(el);
11730
+ if (claims !== void 0) {
11731
+ for (const [channel, published] of claims) {
11732
+ if (!channel.startsWith("style:")) continue;
11733
+ const property = channel.slice(6);
11734
+ const value2 = style.getPropertyValue(property);
11735
+ const priority = style.getPropertyPriority(property);
11736
+ if ((value2 === "" ? null : value2 + (priority ? " !important" : "")) !== published) continue;
11737
+ if (value2 === "") expectedStyle.removeProperty(property);
11738
+ else expectedStyle.setProperty(property, value2, priority);
11739
+ }
11740
+ }
11721
11741
  const expected = expectedStyle.cssText;
11722
11742
  const expectsStyleAttribute = expected !== "";
11723
11743
  if (before === expected && hadStyleAttribute === expectsStyleAttribute) return true;
@@ -12025,7 +12045,7 @@ function isAdoptionControl(error) {
12025
12045
  }
12026
12046
  function presentationFailure(error) {
12027
12047
  const frame = PRESENTATION_HYDRATION;
12028
- if (frame?.revision !== void 0 && !isSuspenseException(error) && !isAdoptionControl(error)) {
12048
+ if (frame !== null && !isSuspenseException(error) && !isAdoptionControl(error)) {
12029
12049
  const failure = new PresentationAdoptionMiss(frame.lease, false);
12030
12050
  failure.failure = error;
12031
12051
  throw failure;
@@ -12036,12 +12056,25 @@ function presentationMiss(retry = true) {
12036
12056
  throw new PresentationAdoptionMiss(PRESENTATION_HYDRATION?.lease, retry);
12037
12057
  }
12038
12058
  function currentPresentation(frame) {
12039
- if (frame.revision === void 0) return true;
12059
+ if (frame.controls !== void 0 && [...frame.controls.values()].some(({ valid }) => !valid()))
12060
+ return false;
12061
+ if (frame.revision === void 0 && frame.controls === void 0) return true;
12040
12062
  const lease = frame.lease;
12041
- return lease.active() && lease.valid?.() !== false && lease.revision?.() === frame.revision && lease.root.parentNode !== null && lease.end?.parentNode === lease.root.parentNode && [...frame.witnesses.values()].every(
12063
+ return lease.active() && lease.valid?.() !== false && lease.revision?.() === frame.revision && lease.root.parentNode !== null && (lease.host === void 0 ? lease.end?.parentNode === lease.root.parentNode : lease.owner === frame.scope.block.idState.renderOwner && frame.scope.block.idState.renderOwner.bindingContainer.contains(lease.root)) && [...frame.witnesses.values()].every(
12042
12064
  (witness) => witness === null || (0, import_native_read_collector.validateNativeReadWitness)(witness)
12043
12065
  );
12044
12066
  }
12067
+ function trackPresentationFrame(frame) {
12068
+ if (frame.current !== void 0) return;
12069
+ frame.current = currentPresentation;
12070
+ (WIP_CAPTURE.presentations ??= []).push(frame);
12071
+ if (frame.hydration === null) return;
12072
+ frame.hydration.presentation = true;
12073
+ for (let block = frame.scope.block; block !== null; block = block.parentBlock) {
12074
+ preserveRootCreatedDom(block);
12075
+ if (block === frame.hydration.rootBlock) break;
12076
+ }
12077
+ }
12045
12078
  function currentPresentations(capture) {
12046
12079
  return capture.presentations?.every((frame) => frame.current(frame)) !== false;
12047
12080
  }
@@ -12077,7 +12110,7 @@ function hasClosedPresentationView(lease, scope, id) {
12077
12110
  return false;
12078
12111
  }
12079
12112
  }
12080
- function beginPresentationHydration(scope, id, supported = false, structural = false, conditionalRest = false) {
12113
+ function beginPresentationHydration(scope, id, supported = false, structural = false, conditionalRest = false, host = false) {
12081
12114
  const owner = scope.block.idState.renderOwner;
12082
12115
  if (PRESENTATION_HYDRATION !== null && PRESENTATION_HYDRATION.scope.block.idState.renderOwner === owner) {
12083
12116
  if (conditionalRest) {
@@ -12089,15 +12122,17 @@ function beginPresentationHydration(scope, id, supported = false, structural = f
12089
12122
  if (owner?.bindingLeases === void 0 || WIP_CAPTURE === null) return null;
12090
12123
  const hydration = activeHydration();
12091
12124
  const lease = [...owner.bindingLeases].find(
12092
- (candidate) => candidate.id === id && (candidate.root === scope.block.startMarker || candidate.root === hydration?.node || candidate.root.nodeType === 8 && candidate.root.nextSibling === hydration?.node)
12125
+ (candidate) => candidate.id === id && (candidate.root === scope.block.startMarker || candidate.root === hydration?.node || candidate.root.nodeType === 8 && candidate.root.nextSibling === hydration?.node || candidate.host !== void 0 && PRESENTATION_PREPARATIONS.get(candidate)?.scope === scope)
12093
12126
  );
12094
12127
  if (lease === void 0) return null;
12128
+ if (!lease.active()) throw new PresentationAdoptionMiss(lease, false);
12129
+ if (host !== (lease.host !== void 0)) throw new PresentationAdoptionMiss(lease, false);
12095
12130
  if (conditionalRest ? !supported || !structural || !hasClosedPresentationView(lease, scope, id) : !supported)
12096
12131
  throw new PresentationAdoptionMiss(lease, false);
12097
12132
  const revision = lease.revision?.();
12098
- if (revision !== void 0 && revision >= 0 && lease.valid?.() === false)
12133
+ if ((revision === void 0 || revision >= 0) && lease.valid?.() === false)
12099
12134
  throw new PresentationAdoptionMiss(lease, false);
12100
- if (revision !== void 0 && (!structural || revision < 0))
12135
+ if (revision !== void 0 && (!structural && !host || revision < 0))
12101
12136
  throw new PresentationAdoptionMiss(lease, revision < 0, revision);
12102
12137
  const pending = PRESENTATION_PREPARATIONS.get(lease);
12103
12138
  const frame = {
@@ -12110,42 +12145,95 @@ function beginPresentationHydration(scope, id, supported = false, structural = f
12110
12145
  readToken: beginNativeReadScope(scope),
12111
12146
  witnessToken: beginNativeReadWitness(),
12112
12147
  witnesses: pending?.scope === scope ? new Map(pending.witnesses) : /* @__PURE__ */ new Map(),
12148
+ ...lease.host === void 0 ? {} : { hostSuccessors: new Map(pending?.scope === scope ? pending.hostSuccessors : void 0) },
12149
+ ...pending?.scope === scope && pending.controls !== void 0 ? { controls: new Map(pending.controls) } : {},
12113
12150
  completed: false,
12114
12151
  lease,
12115
- ...revision === void 0 ? {} : { revision, current: currentPresentation },
12152
+ ...revision === void 0 ? {} : { revision },
12116
12153
  hydration
12117
12154
  };
12118
12155
  PRESENTATION_HYDRATION = frame;
12119
- if (revision !== void 0 && hydration !== null) {
12120
- hydration.presentation = true;
12121
- for (let block = scope.block; block !== null; block = block.parentBlock) {
12122
- preserveRootCreatedDom(block);
12123
- if (block === hydration.rootBlock) break;
12124
- }
12125
- }
12156
+ if (revision !== void 0 || frame.controls !== void 0) trackPresentationFrame(frame);
12126
12157
  PRESENTATION_PREPARATIONS.set(lease, frame);
12127
- if (revision !== void 0) (WIP_CAPTURE.presentations ??= []).push(frame);
12158
+ const hostRefs = host ? WIP_CAPTURE.refs : void 0;
12128
12159
  (WIP_CAPTURE.renderCleanups ??= []).push((discarded) => {
12129
12160
  if (discarded || !frame.completed || owner.disposed || scope.block.disposed || PRESENTATION_PREPARATIONS.get(lease) !== frame)
12130
12161
  return;
12131
12162
  if (!currentPresentation(frame)) {
12132
- frame.hydration?.retryPresentation?.();
12163
+ if (frame.hydration?.retryPresentation !== void 0) frame.hydration.retryPresentation();
12164
+ else throw new PresentationAdoptionMiss(lease, false);
12133
12165
  return;
12134
12166
  }
12135
12167
  PRESENTATION_PREPARATIONS.delete(lease);
12136
12168
  owner.bindingLeases.delete(lease);
12137
12169
  (0, import_dom_binding_handoff.releaseBindingHandoff)(lease);
12170
+ let publicationStarted = false;
12138
12171
  let published = false;
12172
+ let hostFailed = false;
12173
+ let hostFailure;
12139
12174
  try {
12140
12175
  lease.retire(() => {
12141
- for (const writes of frame.writes.values()) for (const write of writes.values()) write();
12176
+ publicationStarted = true;
12177
+ try {
12178
+ for (const writes of frame.writes.values()) for (const write of writes.values()) write();
12179
+ } catch (error) {
12180
+ for (const stop of frame.hostSuccessors?.values() ?? []) {
12181
+ try {
12182
+ stop();
12183
+ } catch {
12184
+ }
12185
+ }
12186
+ frame.hostSuccessors?.clear();
12187
+ for (const [element, control] of frame.controls ?? []) {
12188
+ const binding = control.binding;
12189
+ if (binding.disposed && control.valid(true)) continue;
12190
+ (owner.controlLeases ??= /* @__PURE__ */ new Map()).set(element, control.lease);
12191
+ if (binding.disposed) continue;
12192
+ if (binding.input !== void 0) renderControlledState(element).v = UNCONTROLLED;
12193
+ control.stop = binding.unsubscribe;
12194
+ binding.unsubscribe = void 0;
12195
+ disposeDirectSignalBinding(binding);
12196
+ }
12197
+ for (const control of frame.controls?.values() ?? []) {
12198
+ try {
12199
+ control.stop?.();
12200
+ } catch {
12201
+ }
12202
+ }
12203
+ throw error;
12204
+ }
12142
12205
  published = true;
12143
12206
  });
12144
12207
  } catch (error) {
12145
- if (!published) throw error;
12146
- reportRendererOwnerError(scope, error);
12208
+ if (!publicationStarted) throw error;
12209
+ if (frame.hostSuccessors !== void 0) {
12210
+ hostFailed = true;
12211
+ hostFailure = error;
12212
+ } else reportRendererOwnerError(scope, error);
12147
12213
  } finally {
12214
+ if (frame.hostSuccessors !== void 0 && (!published || lease.valid?.() === false)) {
12215
+ published = false;
12216
+ owner.bindingLeases.add(lease);
12217
+ PRESENTATION_PREPARATIONS.set(lease, frame);
12218
+ for (const entry of hostRefs) if (entry.el === lease.root) entry.ref = null;
12219
+ for (const stop of frame.hostSuccessors.values()) {
12220
+ try {
12221
+ stop();
12222
+ } catch (error) {
12223
+ if (!hostFailed) {
12224
+ hostFailed = true;
12225
+ hostFailure = error;
12226
+ }
12227
+ }
12228
+ }
12229
+ if (!hostFailed) {
12230
+ hostFailed = true;
12231
+ hostFailure = new Error((0, import_error_codes_client_generated.formatClientError)(77));
12232
+ }
12233
+ }
12234
+ frame.hostSuccessors?.clear();
12148
12235
  frame.writes.clear();
12236
+ frame.controls?.clear();
12149
12237
  if (published && !owner.disposed && owner.current !== null && [...frame.witnesses.values()].some(
12150
12238
  (witness) => witness !== null && !(0, import_native_read_collector.validateNativeReadWitness)(witness)
12151
12239
  )) {
@@ -12155,6 +12243,7 @@ function beginPresentationHydration(scope, id, supported = false, structural = f
12155
12243
  }
12156
12244
  frame.witnesses.clear();
12157
12245
  }
12246
+ if (hostFailed) reportRendererOwnerError(scope, hostFailure);
12158
12247
  });
12159
12248
  return frame;
12160
12249
  }
@@ -12173,13 +12262,33 @@ function preparedPresentationAttribute(el, name, value, kind) {
12173
12262
  const result = coerceAttrValue(el, name, value);
12174
12263
  return result === "" && import_constants.BOOLEAN_ATTR_PROPS.has(name.toLowerCase()) ? true : result;
12175
12264
  }
12176
- function preparePresentationSignalAttribute(args, frame) {
12177
- const [scope, previous, element, name, value, site, attributeKind = "attr"] = args;
12265
+ function preparePresentationSignalBinding(args, frame, text = false) {
12266
+ const [scope, previous, element] = args;
12267
+ const name = text ? void 0 : args[3];
12268
+ const value = args[text ? 3 : 4];
12269
+ const site = args[text ? 4 : 5];
12270
+ const attributeKind = text ? void 0 : args[6] ?? "attr";
12271
+ const kind = text ? args[5] ? "textOnlyChild" : "text" : "attribute";
12178
12272
  return runWithBlockSignalOwner(scope, () => {
12179
12273
  const handle = isSignalHandle(value) ? value : null;
12180
- const current = handle === null ? value : handle.get();
12181
- const prepared = preparedPresentationAttribute(element, name, current, attributeKind);
12274
+ const witness = handle !== null && frame.lease.host !== void 0 ? beginNativeReadWitness(true) : -1;
12275
+ let current;
12276
+ let readCompleted = false;
12277
+ try {
12278
+ current = handle === null ? value : handle.get();
12279
+ readCompleted = true;
12280
+ } finally {
12281
+ if (witness >= 0)
12282
+ frame.witnesses.set(handle, finishNativeReadWitness(witness, readCompleted));
12283
+ }
12284
+ if (text && (current !== null && (typeof current === "object" || typeof current === "function") || typeof args[7] !== "string"))
12285
+ presentationMiss(false);
12286
+ const prepared = text ? bindingText(element, current, args[7]) : preparedPresentationAttribute(element, name, current, attributeKind);
12182
12287
  if (handle === null) {
12288
+ if (text) {
12289
+ frame.writes.get(element)?.delete("signalText");
12290
+ return prepared;
12291
+ }
12183
12292
  preparePresentationOperation(
12184
12293
  frame,
12185
12294
  element,
@@ -12189,12 +12298,12 @@ function preparePresentationSignalAttribute(args, frame) {
12189
12298
  return value;
12190
12299
  }
12191
12300
  const prior = previous;
12192
- const reusable = prior?.[DIRECT_SIGNAL_BINDING] === true && !prior.disposed && prior.unsubscribe === void 0 && prior.handle === handle && prior.target === element && prior.site === site && prior.name === name && prior.attributeKind === attributeKind;
12301
+ const reusable = prior?.[DIRECT_SIGNAL_BINDING] === true && !prior.disposed && prior.unsubscribe === void 0 && prior.handle === handle && prior.target === element && prior.kind === kind && prior.site === site && prior.name === name && prior.attributeKind === attributeKind;
12193
12302
  const binding = reusable ? prior : {
12194
12303
  [DIRECT_SIGNAL_BINDING]: true,
12195
12304
  scope,
12196
12305
  target: element,
12197
- kind: "attribute",
12306
+ kind,
12198
12307
  site,
12199
12308
  name,
12200
12309
  attributeKind,
@@ -12202,16 +12311,114 @@ function preparePresentationSignalAttribute(args, frame) {
12202
12311
  value: current,
12203
12312
  disposed: false
12204
12313
  };
12314
+ if (text) binding.text = prepared;
12205
12315
  if (!reusable) registerHookCleanup(scope, () => disposeDirectSignalBinding(binding));
12206
- preparePresentationOperation(frame, element, name, () => {
12316
+ frame.hostSuccessors?.set(binding, () => disposeDirectSignalBinding(binding));
12317
+ preparePresentationOperation(frame, element, name ?? "signalText", () => {
12207
12318
  if (binding.disposed) return;
12208
- writeDirectSignalScalar(element, prepared, "attribute", previous, name, attributeKind);
12319
+ if (!text)
12320
+ writeDirectSignalScalar(element, prepared, "attribute", previous, name, attributeKind);
12209
12321
  binding.value = current;
12210
12322
  runWithBlockSignalOwner(scope, () => activateDirectSignalBinding(binding, void 0));
12211
12323
  });
12212
12324
  return binding;
12213
12325
  });
12214
12326
  }
12327
+ function preparePresentationSignalValue(args, frame) {
12328
+ const [scope, previous, element, handle, site] = args;
12329
+ return runWithBlockSignalOwner(scope, () => {
12330
+ if (element.localName !== "textarea" || element.namespaceURI !== HTML_NS || !isWritableSignal(handle))
12331
+ presentationMiss(false);
12332
+ validateDirectSignalControl(element, site);
12333
+ const value = handle.get();
12334
+ if (typeof value !== "string") presentationMiss(false);
12335
+ const owner = scope.block.idState.renderOwner;
12336
+ const lease = owner.controlLeases?.get(element);
12337
+ const valid = (retired = false) => owner.bindingContainer.contains(element) && (!retired || frame.lease.valid?.() !== false) && (lease !== void 0 && !retired ? lease.owner === owner && lease.active() && runWithBlockSignalOwner(scope, () => lease.matches(handle)) : !(0, import_control_handoff.hasSignalControlBinding)(element, "value") && !(0, import_early_values.hasHydrationControlSignalWriter)(element, "value"));
12338
+ if (!valid()) presentationMiss(false);
12339
+ const prior = previous;
12340
+ const reusable = prior?.[DIRECT_SIGNAL_BINDING] === true && !prior.disposed && prior.input === void 0 && prior.handle === handle && prior.target === element && prior.kind === "value" && prior.site === site;
12341
+ const binding = reusable ? prior : {
12342
+ [DIRECT_SIGNAL_BINDING]: true,
12343
+ scope,
12344
+ target: element,
12345
+ kind: "value",
12346
+ site,
12347
+ handle,
12348
+ value,
12349
+ disposed: false
12350
+ };
12351
+ (frame.controls ??= /* @__PURE__ */ new Map()).set(element, { valid, binding, lease });
12352
+ trackPresentationFrame(frame);
12353
+ if (!reusable) registerHookCleanup(scope, () => disposeDirectSignalBinding(binding));
12354
+ if (binding.unsubscribe === void 0) {
12355
+ const notify = Object.assign(
12356
+ () => {
12357
+ if (binding.controlWriterCleanup !== void 0) updateDirectSignalBinding(binding);
12358
+ },
12359
+ {
12360
+ [import_read_protocol.NATIVE_TRANSITION_CONSUMER]: {
12361
+ active: () => binding.controlWriterCleanup !== void 0 && !binding.disposed && !scope.block.disposed,
12362
+ prepare: () => prepareNativeTransitionBlock(scope.block)
12363
+ }
12364
+ }
12365
+ );
12366
+ const stop = handle[import_types.SIGNAL_BINDING_SUBSCRIBE](
12367
+ notify,
12368
+ () => disposeDirectSignalBinding(binding)
12369
+ );
12370
+ if (typeof stop !== "function") throw new TypeError((0, import_error_codes_client_generated.formatClientError)(74));
12371
+ if (binding.disposed || scope.block.disposed) {
12372
+ stop();
12373
+ presentationMiss(false);
12374
+ }
12375
+ binding.unsubscribe = stop;
12376
+ }
12377
+ preparePresentationOperation(frame, element, "value", () => {
12378
+ if (binding.disposed || scope.block.disposed) return;
12379
+ runWithBlockSignalOwner(scope, () => {
12380
+ if (!valid()) throw new Error((0, import_error_codes_client_generated.formatClientError)(77));
12381
+ const before = (0, import_event_capture.snapshotHydrationControl)(element);
12382
+ const ctrl = armControlled(element);
12383
+ ctrl.composing = before.composing || lease?.composing() === true;
12384
+ if (ctrl.composing) element.addEventListener("blur", onCtrlCompositionEnd);
12385
+ ctrl.v = UNCONTROLLED;
12386
+ let failed = false;
12387
+ let failure;
12388
+ if (lease !== void 0) {
12389
+ try {
12390
+ lease.retire();
12391
+ } catch (error) {
12392
+ failed = true;
12393
+ failure = error;
12394
+ } finally {
12395
+ lease.owner = void 0;
12396
+ }
12397
+ }
12398
+ if (lease !== void 0 && !scope.block.disposed && !valid(true))
12399
+ throw failed ? failure : new Error((0, import_error_codes_client_generated.formatClientError)(77));
12400
+ if (lease !== void 0) owner.controlLeases.delete(element);
12401
+ if (!binding.disposed && !scope.block.disposed) {
12402
+ const snapshot = (0, import_event_capture.snapshotHydrationControl)(element);
12403
+ binding.value = element.value;
12404
+ binding.pendingControl = snapshot.editRevision > (lease === void 0 ? 0 : before.editRevision);
12405
+ installDirectSignalControl(binding);
12406
+ if (!binding.pendingControl) (0, import_event_capture.consumeHydrationControl)(element, snapshot.revision);
12407
+ if (binding.pendingControl) queueDirectSignalControlAdoption(binding);
12408
+ else {
12409
+ const current = readSignalBinding(handle);
12410
+ ctrl.sawV = true;
12411
+ ctrl.v = value;
12412
+ binding.value = current;
12413
+ writeDirectSignalBinding(binding, current);
12414
+ }
12415
+ }
12416
+ if (failed) reportRendererOwnerError(scope, failure);
12417
+ });
12418
+ });
12419
+ return binding;
12420
+ });
12421
+ }
12215
12422
  function presentationHostWrite(writer, ...args) {
12216
12423
  const frame = PRESENTATION_HYDRATION;
12217
12424
  if (frame === null) return writer(...args);
@@ -12243,6 +12450,20 @@ function presentationHostWrite(writer, ...args) {
12243
12450
  function presentationWrite(writer, kind, ...args) {
12244
12451
  const frame = PRESENTATION_HYDRATION;
12245
12452
  if (frame === null) return writer(...args);
12453
+ if (frame.lease.host !== void 0) {
12454
+ const channels = frame.lease.host;
12455
+ const changed2 = kind.endsWith("IfChanged") || kind.startsWith("updateFresh");
12456
+ const element2 = kind === "bindSignalAttribute" || kind === "nativeStyleBinding" || kind === "nativeProjectionBinding" ? args[2] : args[changed2 ? 2 : 0];
12457
+ const keys = kind === "nativeProjectionBinding" ? args[4].map((field) => field === "className" ? "class" : field) : kind === "setStyleProperties" ? args[1].filter((_, index) => index % 2 === 0).map((key2) => "style:" + key2) : [
12458
+ kind === "nativeStyleBinding" || kind === "setStyle" ? "style" : kind === "setStyleProperty" ? "style:" + args[1] : kind.includes("Class") ? "class" : kind === "bindSignalAttribute" ? args[3] : args[changed2 ? 3 : 1]
12459
+ ];
12460
+ if (element2 !== frame.lease.root || keys.some((key2) => !channels.has(key2)) || kind === "bindSignalValue" || kind === "setEventHandler" || kind === "bindSignalText" || kind === "setText" || kind === "markDangerouslySetInnerHTMLChildren")
12461
+ presentationMiss(false);
12462
+ }
12463
+ if (kind === "queueNativeChangeDiagnostic") {
12464
+ preparePresentationOperation(frame, args[0], "nativeChangeDiagnostic", () => writer(...args));
12465
+ return void 0;
12466
+ }
12246
12467
  if (kind === "markDangerouslySetInnerHTMLChildren") {
12247
12468
  const element2 = args[0];
12248
12469
  if (!frame.writes.get(element2)?.has("hostProps") || element2[DANGER_HTML_ACTIVE] === true)
@@ -12250,28 +12471,32 @@ function presentationWrite(writer, kind, ...args) {
12250
12471
  preparePresentationOperation(frame, element2, "hostChildren", () => writer(element2));
12251
12472
  return void 0;
12252
12473
  }
12253
- if (kind === "bindSignalText") {
12254
- const value = args[3];
12255
- if (value !== null && (typeof value === "object" || typeof value === "function") || typeof args[7] !== "string")
12256
- presentationMiss(false);
12257
- return bindingText(args[2], value, args[7]);
12258
- }
12474
+ if (kind === "bindSignalText") return preparePresentationSignalBinding(args, frame, true);
12259
12475
  if (kind === "setText") {
12260
12476
  const text = coerceText(args[1]);
12261
12477
  preparePresentationOperation(frame, args[0], "text", () => writer(args[0], text));
12262
12478
  return void 0;
12263
12479
  }
12264
- if (kind === "bindSignalAttribute") return preparePresentationSignalAttribute(args, frame);
12480
+ if (kind === "bindSignalAttribute") return preparePresentationSignalBinding(args, frame);
12481
+ if (kind === "bindSignalValue") return preparePresentationSignalValue(args, frame);
12265
12482
  if (kind === "nativeStyleBinding" || kind === "nativeProjectionBinding") {
12266
12483
  const [owner, slot, el] = args;
12267
12484
  const style = kind === "nativeStyleBinding";
12268
- nativePresentationBinding(
12269
- owner,
12270
- slot,
12271
- el,
12272
- style ? preparedNativeStyleBody : preparedNativeProjectionBody,
12273
- style ? { el, value: args[3], frame } : { el, compute: args[3], fields: args[4], frame }
12274
- );
12485
+ try {
12486
+ nativePresentationBinding(
12487
+ owner,
12488
+ slot,
12489
+ el,
12490
+ style ? preparedNativeStyleBody : preparedNativeProjectionBody,
12491
+ style ? { el, value: args[3], frame } : { el, compute: args[3], fields: args[4], frame }
12492
+ );
12493
+ } finally {
12494
+ if (frame.hostSuccessors !== void 0) {
12495
+ const binding = owner.slots[slot];
12496
+ if (binding !== void 0)
12497
+ frame.hostSuccessors.set(binding, () => disposeNativeStyleBinding(binding));
12498
+ }
12499
+ }
12275
12500
  return void 0;
12276
12501
  }
12277
12502
  const prepared = args.slice();
@@ -12490,11 +12715,14 @@ function disposeDirectSignalBinding(binding) {
12490
12715
  if (DEFERRED_LAYOUT_DRIVER?.stageAction(() => disposeDirectSignalBinding(binding)) === true)
12491
12716
  return;
12492
12717
  binding.disposed = true;
12493
- binding.unsubscribe?.();
12494
- retireNativeTransitionBlock(binding.scope.block);
12495
- binding.controlWriterCleanup?.();
12496
- if (binding.input !== void 0) {
12497
- domNode(binding.target).removeEventListener("input", binding.input);
12718
+ try {
12719
+ binding.unsubscribe?.();
12720
+ } finally {
12721
+ retireNativeTransitionBlock(binding.scope.block);
12722
+ binding.controlWriterCleanup?.();
12723
+ if (binding.input !== void 0) {
12724
+ domNode(binding.target).removeEventListener("input", binding.input);
12725
+ }
12498
12726
  }
12499
12727
  }
12500
12728
  function directSignalControlValue(binding, snapshot) {
@@ -12659,6 +12887,8 @@ function activateDirectSignalBinding(binding, revision) {
12659
12887
  }
12660
12888
  }
12661
12889
  function createDirectSignalBinding(scope, target, value, site, kind, name, attributeKind, text) {
12890
+ if (kind === "value" && scope.block.idState.renderOwner?.controlLeases?.has(target))
12891
+ presentationMiss(false);
12662
12892
  const handle = isSignalHandle(value) ? value : null;
12663
12893
  const binding = {
12664
12894
  [DIRECT_SIGNAL_BINDING]: true,
@@ -14635,6 +14865,8 @@ function bindSignalHostPropSources(scope, previous, element, sources, site, hasN
14635
14865
  binding.sources = sources;
14636
14866
  }
14637
14867
  const valueControl = winningSignalHostControl(sources, "value");
14868
+ if (valueControl !== null && scope.block.idState.renderOwner?.controlLeases?.has(element))
14869
+ presentationMiss(false);
14638
14870
  const checkedControl = winningSignalHostControl(sources, "checked");
14639
14871
  const controlSnapshot = isWritableSignal(valueControl) || isWritableSignal(checkedControl) ? (0, import_event_capture.snapshotHydrationControl)(element) : null;
14640
14872
  if (controlSnapshot !== null) {
@@ -16287,6 +16519,7 @@ function setNativeChangeDiagnosticMetadata(el, value) {
16287
16519
  if (value === "runtime") queueDevFormDiagnostic(el, CURRENT_SCOPE ?? void 0, true);
16288
16520
  }
16289
16521
  function setValue(el, value) {
16522
+ if (CURRENT_SCOPE?.block.idState.renderOwner?.controlLeases?.has(el)) presentationMiss(false);
16290
16523
  const input = el;
16291
16524
  const ctrl = armControlled(el);
16292
16525
  if (TRANSITION_JOURNAL !== null) journalControlled(el, "value", "defaultValue");
@@ -27046,6 +27279,11 @@ function makeRoot(container, rootBlock, currentBody, currentKey, idState, output
27046
27279
  }
27047
27280
  unmounted = true;
27048
27281
  renderOwner.disposed = true;
27282
+ if (renderOwner.controlLeases !== void 0) {
27283
+ for (const lease of renderOwner.controlLeases.values())
27284
+ if (lease !== void 0) lease.owner = void 0;
27285
+ renderOwner.controlLeases.clear();
27286
+ }
27049
27287
  if (renderOwner.bindingLeases !== void 0) {
27050
27288
  for (const lease of renderOwner.bindingLeases) {
27051
27289
  (0, import_dom_binding_handoff.releaseBindingHandoff)(lease);
@@ -27106,7 +27344,8 @@ function makeRoot(container, rootBlock, currentBody, currentKey, idState, output
27106
27344
  }
27107
27345
  function createRootWithOutputHandler(container, options, outputHandler) {
27108
27346
  assertValidRootContainer(container);
27109
- if (options?.bindingLeases !== void 0) throw new Error((0, import_error_codes_client_generated.formatClientError)(76));
27347
+ if (options?.bindingLeases !== void 0 || options?.controlLeases !== void 0)
27348
+ throw new Error((0, import_error_codes_client_generated.formatClientError)(76));
27110
27349
  options = warnCreateRootElementOption(options);
27111
27350
  const ownerToken = claimRootContainer(container);
27112
27351
  registerDelegationTarget(container, true);
@@ -27166,12 +27405,20 @@ function hydrateRoot(container, bodyOrElement, propsOrOptions, rootOptions) {
27166
27405
  const bindingLeases = rootOptions?.bindingLeases?.map((handle) => {
27167
27406
  const capability = handle;
27168
27407
  const lease = capability[import_dom_binding_handoff.BINDING_HANDOFF]?.();
27169
- if (lease === void 0 || !lease.active() || lease.owner !== void 0 || !container.contains(lease.root))
27408
+ if (lease === void 0 || !lease.active() || lease.host !== void 0 && lease.valid?.() === false || lease.owner !== void 0 || !container.contains(lease.root))
27170
27409
  throw new Error((0, import_error_codes_client_generated.formatClientError)(77));
27171
27410
  return lease;
27172
27411
  });
27173
27412
  if (bindingLeases !== void 0 && new Set(bindingLeases).size !== bindingLeases.length)
27174
27413
  throw new Error((0, import_error_codes_client_generated.formatClientError)(78));
27414
+ const controlLeases = rootOptions?.controlLeases?.map((handle) => {
27415
+ const lease = handle?.[import_control_handoff.CONTROL_HANDOFF]?.();
27416
+ if (!bindingLeases?.length || lease === void 0 || !lease.active() || lease.owner !== void 0 || lease.channel !== "value" || lease.control.localName !== "textarea" || !container.contains(lease.control))
27417
+ throw new Error((0, import_error_codes_client_generated.formatClientError)(77));
27418
+ return lease;
27419
+ });
27420
+ if (controlLeases !== void 0 && new Set(controlLeases.map((lease) => lease.control)).size !== controlLeases.length)
27421
+ throw new Error((0, import_error_codes_client_generated.formatClientError)(78));
27175
27422
  const nativeSidecar = findHydrateSeedSidecar(container, import_native_read_seeds.NATIVE_SIGNAL_SEED_ATTR);
27176
27423
  const nativeManifest = nativeSidecar === null ? void 0 : (0, import_native_read_seeds.parseNativeSignalManifest)(
27177
27424
  (STAGED_DOM?.view(nativeSidecar) ?? nativeSidecar).textContent || ""
@@ -27233,6 +27480,10 @@ function hydrateRoot(container, bodyOrElement, propsOrOptions, rootOptions) {
27233
27480
  rootOptions
27234
27481
  );
27235
27482
  const owner = idState.renderOwner;
27483
+ if (controlLeases !== void 0) {
27484
+ owner.controlLeases = new Map(controlLeases.map((lease) => [lease.control, lease]));
27485
+ for (const lease of controlLeases) lease.owner = owner;
27486
+ }
27236
27487
  if (bindingLeases !== void 0) {
27237
27488
  owner.bindingLeases = new Set(bindingLeases);
27238
27489
  owner.bindingContainer = container;
@@ -27266,7 +27517,7 @@ function hydrateRoot(container, bodyOrElement, propsOrOptions, rootOptions) {
27266
27517
  while (firstNode !== null && (firstNode.nodeType === 10 || isRendererHydrationStyle(firstNode)))
27267
27518
  firstNode = getNextSibling(firstNode);
27268
27519
  const hydration = new HydrationCapability(rootBlock, firstNode, seeds);
27269
- if (bindingLeases?.some((lease) => lease.revision !== void 0)) {
27520
+ if (bindingLeases?.length) {
27270
27521
  const attempted = rootBlock;
27271
27522
  hydration.retryPresentation = () => {
27272
27523
  if (owner.disposed || owner.current !== attempted) return;
@@ -27274,7 +27525,12 @@ function hydrateRoot(container, bodyOrElement, propsOrOptions, rootOptions) {
27274
27525
  collectVisibleSubtreeRefs(attempted, refs);
27275
27526
  withRefDetachSuppression(refs, () => unmountBlock(attempted, false));
27276
27527
  queueMicrotask(() => {
27277
- if (!owner.disposed && owner.current === attempted) adopt();
27528
+ if (owner.disposed || owner.current !== attempted) return;
27529
+ try {
27530
+ adopt();
27531
+ } catch (error) {
27532
+ if (!reportUncaughtError(rootBlock, error)) throw error;
27533
+ }
27278
27534
  });
27279
27535
  };
27280
27536
  }
@@ -26,6 +26,7 @@ __export(streamed_signals_exports, {
26
26
  });
27
27
  module.exports = __toCommonJS(streamed_signals_exports);
28
28
  var import_data_encoding = require("../data-encoding.cjs");
29
+ var import_stream_protocol = require("../stream-protocol.cjs");
29
30
  var import_streamed_signals_protocol = require("../streamed-signals-protocol.cjs");
30
31
  var import_signal_query_observation = require("./signal-query-observation.cjs");
31
32
  const DEFAULT_MAX_FRAME_BYTES = 4 * 1024 * 1024;
@@ -182,12 +183,12 @@ function escapeAttribute(value) {
182
183
  }
183
184
  function streamedRendererFrameScript(frame, nonce) {
184
185
  const encoded = (0, import_streamed_signals_protocol.encodeStreamedRendererFrameForScript)(frame);
185
- return `<script${nonce === void 0 ? "" : ` nonce="${escapeAttribute(nonce)}"`}>globalThis.__octaneStreamedRenderer.receive(${encoded});</script>`;
186
+ return `<script ${import_stream_protocol.STREAM_SCRIPT_ATTR}${nonce === void 0 ? "" : ` nonce="${escapeAttribute(nonce)}"`}>globalThis.__octaneStreamedRenderer.receive(${encoded});</script>`;
186
187
  }
187
188
  function streamedSignalSelectionScript(identity, nonce) {
188
189
  if (!(0, import_streamed_signals_protocol.isStreamFrameIdentity)(identity)) throw new TypeError("Invalid streamed signal identity.");
189
190
  const encoded = JSON.stringify(identity).replace(/&/g, "\\u0026").replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
190
- return `<script${nonce === void 0 ? "" : ` nonce="${escapeAttribute(nonce)}"`}>(function(g){var k="__octaneStreamedRenderer",e=g[k];if(!e){var q=[];g[k]={version:1,frames:q,receive:function(f){if(q.length>=512){this.overflow=true;return;}q.push(f);}};}var z="__octaneStreamedSignalSelections",v=g[z];if(!v){var a=[];v=g[z]={version:1,identities:a,register:function(i){if(a.length>=256){this.overflow=true;return;}a.push(i);}};}v.register(${encoded});})(globalThis);</script>`;
191
+ return `<script ${import_stream_protocol.STREAM_SCRIPT_ATTR}${nonce === void 0 ? "" : ` nonce="${escapeAttribute(nonce)}"`}>(function(g){var k="__octaneStreamedRenderer",e=g[k];if(!e){var q=[];g[k]={version:1,frames:q,receive:function(f){if(q.length>=512){this.overflow=true;return;}q.push(f);}};}var z="__octaneStreamedSignalSelections",v=g[z];if(!v){var a=[];v=g[z]={version:1,identities:a,register:function(i){if(a.length>=256){this.overflow=true;return;}a.push(i);}};}v.register(${encoded});})(globalThis);</script>`;
191
192
  }
192
193
  function createStreamedSignalInjection(identity, result, options = {}) {
193
194
  const budget = limits(options);