octane 0.3.0 → 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 (55) 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/index.cjs +2 -0
  8. package/dist/cjs/runtime-tags.cjs +55 -0
  9. package/dist/cjs/runtime.cjs +235 -148
  10. package/dist/cjs/runtime.server.cjs +110 -80
  11. package/dist/cjs/server/streamed-signals.cjs +102 -64
  12. package/dist/cjs/signals/control-binding.cjs +2 -1
  13. package/dist/cjs/stream-protocol.cjs +9 -8
  14. package/dist/cjs/version.cjs +1 -1
  15. package/dist/compiler/compile.js +550 -35
  16. package/dist/compiler/dom-bindings.js +5 -0
  17. package/dist/compiler/hydrate-boundaries.js +118 -0
  18. package/dist/compiler/private-context.js +160 -0
  19. package/dist/constants.d.ts +7 -18
  20. package/dist/constants.js +11 -9
  21. package/dist/css.d.ts +7 -0
  22. package/dist/css.js +4 -0
  23. package/dist/dom-binding-program.js +12 -5
  24. package/dist/dom-binding-protocol.d.ts +14 -1
  25. package/dist/dom-binding-protocol.js +40 -14
  26. package/dist/hydration/control-capture.d.ts +2 -0
  27. package/dist/hydration/control-capture.js +18 -5
  28. package/dist/hydration/event-capture.js +1 -2
  29. package/dist/hydration/independent-island.js +5 -5
  30. package/dist/hydration/stream-delivery.d.ts +1 -1
  31. package/dist/hydration/stream-delivery.js +16 -9
  32. package/dist/hydration/stream-result-receiver.d.ts +1 -0
  33. package/dist/hydration/stream-result-receiver.js +8 -4
  34. package/dist/hydration-markers.d.ts +30 -0
  35. package/dist/hydration-markers.js +27 -1
  36. package/dist/index.d.ts +1 -1
  37. package/dist/index.js +2 -0
  38. package/dist/react/index.js +1 -1
  39. package/dist/react/react-compat-shared.js +5 -3
  40. package/dist/react/shared.d.ts +1 -3
  41. package/dist/react/shared.js +1 -1
  42. package/dist/runtime-tags.d.ts +34 -0
  43. package/dist/runtime-tags.js +22 -0
  44. package/dist/runtime.d.ts +9 -14
  45. package/dist/runtime.js +213 -106
  46. package/dist/runtime.server.d.ts +10 -5
  47. package/dist/runtime.server.js +101 -56
  48. package/dist/server/streamed-signals.d.ts +1 -0
  49. package/dist/server/streamed-signals.js +102 -64
  50. package/dist/signals/control-binding.js +4 -2
  51. package/dist/stream-protocol.js +20 -9
  52. package/dist/universal-core.js +8 -4
  53. package/dist/universal-native.js +1 -1
  54. package/dist/version.js +1 -1
  55. package/package.json +3 -3
@@ -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';
@@ -46,6 +47,12 @@ export declare function finishNativeReadWitness(token: number, completed: boolea
46
47
  /** @internal Shared automatic-cache witness ABI. */
47
48
  export declare function replayNativeReadWitness(witness: NativeReadWitness | null | undefined): void;
48
49
  type ServerSignalInstanceKey = string | Frame;
50
+ interface ServerSignalListKeys {
51
+ parent: ServerSignalListKeys | null;
52
+ key: unknown;
53
+ mapped: boolean;
54
+ values: readonly string[] | null;
55
+ }
49
56
  interface InjectedStyle {
50
57
  css: string;
51
58
  nonce?: string;
@@ -63,8 +70,8 @@ interface Frame {
63
70
  namespace: 'html' | 'svg' | 'mathml' | undefined;
64
71
  signalParentKey?: ServerSignalInstanceKey;
65
72
  signalInvocationSite?: string;
66
- signalListKeys?: readonly string[];
67
- signalKey?: string;
73
+ signalListKeys?: ServerSignalListKeys | null;
74
+ signalKey?: unknown;
68
75
  signalInstanceKey?: string;
69
76
  }
70
77
  type ScopedCounts = (string | number)[] | Map<string, number>;
@@ -72,13 +79,12 @@ type ScopedCounts = (string | number)[] | Map<string, number>;
72
79
  export declare function ssrElement(tag: string, location: string | undefined, render: () => string, htmlIntegrationPoint?: boolean): string;
73
80
  /** Compiler ABI: validate one authored static or dynamic text child in DEV SSR. */
74
81
  export declare function ssrNestingText(value: unknown): string;
75
- declare const ELEMENT_TAG: unique symbol;
76
82
  /**
77
83
  * React-compatible Fragment sentinel. Value-position `<Fragment>` sites compile
78
84
  * to ordinary element descriptors in both modes; ssrChild recognizes this type
79
85
  * and flattens its children with the same wrapper/key rules as the client.
80
86
  */
81
- export declare const Fragment: unique symbol;
87
+ export declare const Fragment: typeof FRAGMENT_TAG;
82
88
  /**
83
89
  * React-19 `<Activity>` sentinel. Direct template sites lower to `ssrActivity`;
84
90
  * generic component and descriptor sites dispatch by this same symbol identity.
@@ -418,7 +424,6 @@ export declare const ErrorBoundary: (props: {
418
424
  fallback?: unknown;
419
425
  children?: unknown;
420
426
  }, scope: SSRScope) => string;
421
- declare const CONTEXT_TAG: unique symbol;
422
427
  export interface Context<T> {
423
428
  (props: {
424
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,
@@ -269,7 +286,7 @@ let SIGNAL_COMPONENT_INSTANCE_KEY = "";
269
286
  let SERVER_SIGNAL_OWNER_ACTIVE = false;
270
287
  let SIGNAL_CONTROL_SITE = "";
271
288
  const EMPTY_SIGNAL_LIST_KEYS = [];
272
- let SIGNAL_LIST_KEYS = EMPTY_SIGNAL_LIST_KEYS;
289
+ let SIGNAL_LIST_KEYS = null;
273
290
  function newStyleCollector() {
274
291
  const collector = /* @__PURE__ */ new Map();
275
292
  collector.replay = null;
@@ -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) {
@@ -1648,10 +1663,7 @@ function enterAsyncArm(armKey, mapped = false) {
1648
1663
  const occurrence = frame === null ? 0 : nextFrameOccurrence(frame, "@arm-position:");
1649
1664
  const fallbackPosition = armKey !== null && (typeof armKey === "object" || typeof armKey === "function" || typeof armKey === "symbol") ? previous + "|@arm-position:" + occurrence : void 0;
1650
1665
  if (SERVER_SIGNAL_BINDINGS_POTENTIAL && SIGNAL_CONTROL_SITE.charCodeAt(0) === 102) {
1651
- SIGNAL_LIST_KEYS = [
1652
- ...SIGNAL_LIST_KEYS,
1653
- signalIdentityKey(mapped ? "k" + String(armKey) : armKey)
1654
- ];
1666
+ SIGNAL_LIST_KEYS = { parent: SIGNAL_LIST_KEYS, key: armKey, mapped, values: null };
1655
1667
  }
1656
1668
  ASYNC_SCOPE = previous + "|@arm:" + asyncIdentityKey(armKey, false, fallbackPosition);
1657
1669
  }
@@ -2720,10 +2732,27 @@ function signalIdentityKey(value) {
2720
2732
  function serverStructuralSignalInstanceKey(invocationSite, key) {
2721
2733
  return resolveServerSignalInstanceKey(SIGNAL_COMPONENT_INSTANCE_KEY) + JSON.stringify([
2722
2734
  invocationSite ?? "legacy",
2723
- SIGNAL_LIST_KEYS,
2735
+ resolveServerSignalListKeys(SIGNAL_LIST_KEYS),
2724
2736
  key != null ? signalIdentityKey(key) : ""
2725
2737
  ]);
2726
2738
  }
2739
+ function resolveServerSignalListKeys(keys) {
2740
+ if (keys === null) return EMPTY_SIGNAL_LIST_KEYS;
2741
+ if (keys.values !== null) return keys.values;
2742
+ const pending = [];
2743
+ let parent = keys;
2744
+ while (parent !== null && parent.values === null) {
2745
+ pending.push(parent);
2746
+ parent = parent.parent;
2747
+ }
2748
+ let values = parent?.values ?? EMPTY_SIGNAL_LIST_KEYS;
2749
+ for (let index = pending.length - 1; index >= 0; index--) {
2750
+ const entry = pending[index];
2751
+ values = [...values, signalIdentityKey(entry.mapped ? "k" + String(entry.key) : entry.key)];
2752
+ entry.values = values;
2753
+ }
2754
+ return values;
2755
+ }
2727
2756
  function resolveServerSignalInstanceKey(identity) {
2728
2757
  if (typeof identity === "string") return identity;
2729
2758
  if (identity.signalInstanceKey !== void 0) return identity.signalInstanceKey;
@@ -2740,8 +2769,8 @@ function resolveServerSignalInstanceKey(identity) {
2740
2769
  const frame = pending[index];
2741
2770
  identity += JSON.stringify([
2742
2771
  frame.signalInvocationSite ?? "legacy",
2743
- frame.signalListKeys,
2744
- frame.signalKey
2772
+ resolveServerSignalListKeys(frame.signalListKeys ?? null),
2773
+ frame.signalKey != null ? signalIdentityKey(frame.signalKey) : ""
2745
2774
  ]);
2746
2775
  frame.signalInstanceKey = identity;
2747
2776
  }
@@ -2846,7 +2875,7 @@ function renderComponentFramed(comp, props, parent, frame, inherit, instanceKey,
2846
2875
  ASYNC_SCOPE = frame.asyncScope;
2847
2876
  if (instanceKey !== void 0) SIGNAL_COMPONENT_INSTANCE_KEY = instanceKey;
2848
2877
  SIGNAL_CONTROL_SITE = "";
2849
- SIGNAL_LIST_KEYS = EMPTY_SIGNAL_LIST_KEYS;
2878
+ SIGNAL_LIST_KEYS = null;
2850
2879
  const nativeToken = NATIVE_READ_COLLECTOR === null ? -1 : beginActiveNativeReadScope(scope);
2851
2880
  let nativeCompleted = false;
2852
2881
  try {
@@ -2945,34 +2974,36 @@ function ssrComponent(parent, comp, props, inherit, key, identityScoped, invocat
2945
2974
  });
2946
2975
  }
2947
2976
  const pf = FRAME;
2948
- const frame = pf === null ? {
2949
- parent: null,
2950
- seg: 0,
2977
+ const seg = pf === null ? 0 : nextChildSegment(pf);
2978
+ const namespace = explicitNamespace ?? pf?.namespace;
2979
+ const potentialSignalKey = signalInstanceKey === void 0 && SERVER_SIGNAL_BINDINGS_POTENTIAL;
2980
+ const frame = potentialSignalKey ? {
2981
+ parent: pf,
2982
+ seg,
2951
2983
  nextChild: 0,
2952
2984
  scopedChildren: null,
2953
2985
  occ: null,
2954
2986
  path: null,
2955
2987
  deferred: false,
2956
2988
  asyncScope: ASYNC_SCOPE,
2957
- namespace: explicitNamespace ?? void 0
2989
+ namespace,
2990
+ signalParentKey: SIGNAL_COMPONENT_INSTANCE_KEY,
2991
+ signalInvocationSite: invocationSite,
2992
+ signalListKeys: SIGNAL_LIST_KEYS,
2993
+ signalKey: key,
2994
+ signalInstanceKey: void 0
2958
2995
  } : {
2959
2996
  parent: pf,
2960
- seg: nextChildSegment(pf),
2997
+ seg,
2961
2998
  nextChild: 0,
2962
2999
  scopedChildren: null,
2963
3000
  occ: null,
2964
3001
  path: null,
2965
3002
  deferred: false,
2966
3003
  asyncScope: ASYNC_SCOPE,
2967
- namespace: explicitNamespace ?? pf.namespace
3004
+ namespace
2968
3005
  };
2969
- if (signalInstanceKey === void 0 && SERVER_SIGNAL_BINDINGS_POTENTIAL) {
2970
- frame.signalParentKey = SIGNAL_COMPONENT_INSTANCE_KEY;
2971
- frame.signalInvocationSite = invocationSite;
2972
- frame.signalListKeys = SIGNAL_LIST_KEYS;
2973
- frame.signalKey = key != null ? signalIdentityKey(key) : "";
2974
- signalInstanceKey = frame;
2975
- }
3006
+ if (potentialSignalKey) signalInstanceKey = frame;
2976
3007
  return renderComponentFramed(
2977
3008
  comp,
2978
3009
  props,
@@ -3055,7 +3086,7 @@ function withServerIndependentIdentity(prefix, idSeed, render) {
3055
3086
  SIGNAL_INSTANCE_PREFIX = prefix;
3056
3087
  SIGNAL_COMPONENT_INSTANCE_KEY = JSON.stringify([prefix, "root"]);
3057
3088
  SIGNAL_CONTROL_SITE = "";
3058
- SIGNAL_LIST_KEYS = EMPTY_SIGNAL_LIST_KEYS;
3089
+ SIGNAL_LIST_KEYS = null;
3059
3090
  ID_PREFIX = prefix + "-";
3060
3091
  ID_COUNTER = idSeed;
3061
3092
  try {
@@ -3209,7 +3240,7 @@ const Suspense = /* @__PURE__ */ markComponentFlags(
3209
3240
  },
3210
3241
  COMPONENT_FLAG_BOUNDARY,
3211
3242
  "Suspense",
3212
- /* @__PURE__ */ Symbol.for("octane.suspense")
3243
+ SUSPENSE_TAG
3213
3244
  );
3214
3245
  let VT_SSR_TRY_SEQ = 0;
3215
3246
  let VT_SSR_HAS_CANDIDATES = false;
@@ -3392,11 +3423,7 @@ function vtSsrAnnotateScope(html) {
3392
3423
  true
3393
3424
  );
3394
3425
  const valid = roots === 1 && !sentinel && !text;
3395
- if (valid)
3396
- injectStyle(
3397
- "octane-view-transition-scope",
3398
- '[vt-scope="element"]{view-transition-scope:all!important}'
3399
- );
3426
+ if (valid) injectStyle(VIEW_TRANSITION_SCOPE_STYLE_ID, VIEW_TRANSITION_SCOPE_CSS);
3400
3427
  return vtSsrMapTags(
3401
3428
  html,
3402
3429
  (open) => vtSsrInject(open, [["vt-scope", valid ? "element" : "none"]]),
@@ -3588,7 +3615,6 @@ const ErrorBoundary = /* @__PURE__ */ markComponentFlags(
3588
3615
  COMPONENT_FLAG_BOUNDARY,
3589
3616
  "ErrorBoundary"
3590
3617
  );
3591
- const CONTEXT_TAG = /* @__PURE__ */ Symbol.for("octane.context");
3592
3618
  function createContext(defaultValue) {
3593
3619
  const ctx = function ProviderBody(props, scope) {
3594
3620
  return ssrHtml(renderServerContextProvider(ctx, props, scope));
@@ -4187,7 +4213,6 @@ function warmChild(comp, props) {
4187
4213
  }
4188
4214
  }
4189
4215
  let LAZY_ID = 0;
4190
- const LAZY_COMPONENT = /* @__PURE__ */ Symbol.for("octane.lazy");
4191
4216
  function resolveLazyModule(mod) {
4192
4217
  let comp = mod;
4193
4218
  if (mod != null) {
@@ -4436,7 +4461,7 @@ function useDebugValue(_value, _format) {
4436
4461
  function requestFormReset(_form) {
4437
4462
  }
4438
4463
  function useId() {
4439
- return ":" + ID_PREFIX + "in-" + (ID_COUNTER++).toString(36) + ":";
4464
+ return formatUseId(ID_PREFIX, ID_COUNTER++);
4440
4465
  }
4441
4466
  function throwOnServerEffectEventCall() {
4442
4467
  throw new Error(formatServerError(11));
@@ -4572,7 +4597,6 @@ function startTransition(fn) {
4572
4597
  function flushSync(fn) {
4573
4598
  return fn();
4574
4599
  }
4575
- const CHILDREN_BLOCK = /* @__PURE__ */ Symbol.for("octane.childrenBlock");
4576
4600
  function markChildrenBlock(fn) {
4577
4601
  if (typeof fn === "function") {
4578
4602
  fn[CHILDREN_BLOCK] = true;
@@ -4947,7 +4971,7 @@ function runFullFramedPass(component, props, resolved, nonceAttr = "", identifie
4947
4971
  SIGNAL_COMPONENT_INSTANCE_KEY = JSON.stringify([identifierPrefix, "root"]);
4948
4972
  SERVER_SIGNAL_OWNER_ACTIVE = false;
4949
4973
  SIGNAL_CONTROL_SITE = "";
4950
- SIGNAL_LIST_KEYS = EMPTY_SIGNAL_LIST_KEYS;
4974
+ SIGNAL_LIST_KEYS = null;
4951
4975
  NONCE_ATTR = nonceAttr;
4952
4976
  ASYNC_SCOPE = "";
4953
4977
  MARKERS = markers;
@@ -5069,7 +5093,7 @@ function runDiscoveryRound(jobs, resolved, identifierPrefix) {
5069
5093
  SIGNAL_COMPONENT_INSTANCE_KEY = JSON.stringify([identifierPrefix, "root"]);
5070
5094
  SERVER_SIGNAL_OWNER_ACTIVE = false;
5071
5095
  SIGNAL_CONTROL_SITE = "";
5072
- SIGNAL_LIST_KEYS = EMPTY_SIGNAL_LIST_KEYS;
5096
+ SIGNAL_LIST_KEYS = null;
5073
5097
  NONCE_ATTR = "";
5074
5098
  ASYNC_SCOPE = "";
5075
5099
  MARKERS = true;
@@ -6420,7 +6444,19 @@ function boundaryErrorChunk(b, nonceAttr) {
6420
6444
  const serverOwnedStatic = b.serverOwnedStatic ? ",1" : "";
6421
6445
  return "<script " + STREAM_SCRIPT_ATTR + nonceAttr + ">$OCTRX(" + JSON.stringify(b.id).replace(/</g, "\\u003c") + serverOwnedStatic + ")</script>";
6422
6446
  }
6423
- async function runStream(component, props, options, sink, resolved) {
6447
+ function createInjectionCanceler(injection) {
6448
+ if (injection === void 0) return NOOP;
6449
+ let cancelled = false;
6450
+ return (error) => {
6451
+ if (cancelled) return;
6452
+ cancelled = true;
6453
+ try {
6454
+ injection.cancel?.(error);
6455
+ } catch {
6456
+ }
6457
+ };
6458
+ }
6459
+ async function runStream(component, props, options, sink, resolved, cancelInjection) {
6424
6460
  const timeoutMs = options?.timeoutMs ?? SUSPENSE_TIMEOUT_MS;
6425
6461
  const signal = options?.signal;
6426
6462
  const nonceAttr = nonceAttrOf(options);
@@ -6502,7 +6538,15 @@ async function runStream(component, props, options, sink, resolved) {
6502
6538
  injection.accepted?.();
6503
6539
  });
6504
6540
  };
6505
- const recoveryInjection = injection === void 0 ? void 0 : async () => {
6541
+ const recoveryInjection = injection === void 0 ? void 0 : async (error) => {
6542
+ let queued = "";
6543
+ if (!injectionFailed) {
6544
+ try {
6545
+ queued = injection.take();
6546
+ } catch {
6547
+ }
6548
+ }
6549
+ cancelInjection(error);
6506
6550
  if (signal?.aborted) {
6507
6551
  await writeChain;
6508
6552
  for (const html of unacceptedInjection) {
@@ -6511,13 +6555,6 @@ async function runStream(component, props, options, sink, resolved) {
6511
6555
  }
6512
6556
  unacceptedInjection.length = 0;
6513
6557
  }
6514
- if (injectionFailed) return "";
6515
- let queued;
6516
- try {
6517
- queued = injection.take();
6518
- } catch {
6519
- return "";
6520
- }
6521
6558
  if (queued !== "" && signal?.aborted) {
6522
6559
  const replay = write(queued, "recovery");
6523
6560
  if (replay !== void 0) await replay;
@@ -6833,7 +6870,7 @@ async function runStream(component, props, options, sink, resolved) {
6833
6870
  let tail = "";
6834
6871
  if (recoveryInjection !== void 0) {
6835
6872
  try {
6836
- tail = await recoveryInjection();
6873
+ tail = await recoveryInjection(err);
6837
6874
  } catch {
6838
6875
  }
6839
6876
  }
@@ -6877,7 +6914,7 @@ async function runStream(component, props, options, sink, resolved) {
6877
6914
  injectionUnsubscribe = void 0;
6878
6915
  let terminal = "";
6879
6916
  try {
6880
- terminal = await recoveryInjection();
6917
+ terminal = await recoveryInjection(err);
6881
6918
  } catch {
6882
6919
  }
6883
6920
  terminal += heldDocumentTail;
@@ -7045,6 +7082,7 @@ function renderToPipeableStream(entryComponent, props, options) {
7045
7082
  const beginRender = (preparedOptions) => {
7046
7083
  const renderOptions = { ...preparedOptions, signal: controller.signal };
7047
7084
  const resolved = newResolvedMap(renderOptions);
7085
+ const cancelInjection = createInjectionCanceler(renderOptions.injection);
7048
7086
  void runStream(
7049
7087
  component,
7050
7088
  props,
@@ -7057,6 +7095,7 @@ function renderToPipeableStream(entryComponent, props, options) {
7057
7095
  options?.onShellReady?.();
7058
7096
  },
7059
7097
  shellError(err) {
7098
+ cancelInjection(err);
7060
7099
  releaseServerRenderResources(resolved);
7061
7100
  shellFailure = { error: err };
7062
7101
  options?.onShellError?.(err);
@@ -7067,14 +7106,17 @@ function renderToPipeableStream(entryComponent, props, options) {
7067
7106
  options?.onAllReady?.();
7068
7107
  flushEnd();
7069
7108
  },
7070
- fatal() {
7109
+ fatal(err) {
7110
+ cancelInjection(err);
7071
7111
  releaseServerRenderResources(resolved);
7072
7112
  options?.onAllReady?.();
7073
7113
  flushEnd();
7074
7114
  }
7075
7115
  },
7076
- resolved
7116
+ resolved,
7117
+ cancelInjection
7077
7118
  ).catch((err) => {
7119
+ cancelInjection(err);
7078
7120
  releaseServerRenderResources(resolved);
7079
7121
  options?.onError?.(err);
7080
7122
  flushEnd();
@@ -7258,6 +7300,7 @@ function renderToReadableStream(entryComponent, props, options) {
7258
7300
  };
7259
7301
  }
7260
7302
  const resolved = newResolvedMap(renderOptions);
7303
+ const cancelInjection = createInjectionCanceler(renderOptions.injection);
7261
7304
  const release = () => {
7262
7305
  if (released) return;
7263
7306
  released = true;
@@ -7266,6 +7309,7 @@ function renderToReadableStream(entryComponent, props, options) {
7266
7309
  const settleFailure = (error) => {
7267
7310
  if (terminal) return;
7268
7311
  terminal = true;
7312
+ cancelInjection(error);
7269
7313
  try {
7270
7314
  release();
7271
7315
  } catch (err) {
@@ -7318,7 +7362,8 @@ function renderToReadableStream(entryComponent, props, options) {
7318
7362
  settleFailure(err);
7319
7363
  }
7320
7364
  },
7321
- resolved
7365
+ resolved,
7366
+ cancelInjection
7322
7367
  ).catch((err) => {
7323
7368
  renderOptions.onError?.(err);
7324
7369
  settleFailure(err);
@@ -4,6 +4,7 @@ import type { ServerSignalQueryAttempt } from '../signals/query-attempt-observer
4
4
  export interface StreamedRendererLimits {
5
5
  readonly maxFrameBytes?: number;
6
6
  readonly maxTotalBytes?: number;
7
+ /** Maximum wait for producer progress; queued data and sink backpressure pause it. */
7
8
  readonly timeoutMs?: number;
8
9
  }
9
10
  export interface StreamedSignalResultOptions extends StreamedRendererLimits {