octane 0.4.2 → 0.4.3

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 (57) hide show
  1. package/dist/cjs/context-identity.cjs +29 -0
  2. package/dist/cjs/dom-stage.cjs +24 -18
  3. package/dist/cjs/error-codes.server.generated.cjs +5 -0
  4. package/dist/cjs/hydration-markers.cjs +12 -0
  5. package/dist/cjs/index.cjs +2 -0
  6. package/dist/cjs/runtime.cjs +253 -393
  7. package/dist/cjs/runtime.server.cjs +137 -35
  8. package/dist/cjs/server/index.cjs +2 -0
  9. package/dist/cjs/server/streamed-signals.cjs +41 -9
  10. package/dist/cjs/signals/client.cjs +1 -6
  11. package/dist/cjs/signals/engine.cjs +1 -12
  12. package/dist/cjs/version.cjs +1 -1
  13. package/dist/compiler/client-only-server.js +1 -28
  14. package/dist/compiler/compile-renderer-boundaries.js +1 -22
  15. package/dist/compiler/compile-universal.js +1 -22
  16. package/dist/compiler/compile.js +782 -359
  17. package/dist/compiler/dom-binding-fixed-props.js +11 -1
  18. package/dist/compiler/generated-origin.js +46 -0
  19. package/dist/compiler/hydrate-boundaries.js +88 -52
  20. package/dist/compiler/plain-hook-memo.js +5 -1
  21. package/dist/compiler/pure-factories.js +66 -0
  22. package/dist/compiler/register.js +4 -1
  23. package/dist/compiler/slot-hooks.js +113 -186
  24. package/dist/compiler/typescript-lowering.js +763 -0
  25. package/dist/compiler/void-roots.js +239 -0
  26. package/dist/compiler/volar.js +91 -38
  27. package/dist/context-identity.d.ts +14 -0
  28. package/dist/context-identity.js +28 -0
  29. package/dist/dom-stage.js +24 -18
  30. package/dist/error-codes.server.generated.d.ts +1 -0
  31. package/dist/error-codes.server.generated.js +5 -0
  32. package/dist/hydration/idle.js +1 -0
  33. package/dist/hydration/independent-island.js +53 -2
  34. package/dist/hydration/media.js +1 -0
  35. package/dist/hydration/types.d.ts +5 -0
  36. package/dist/hydration/visible.js +1 -0
  37. package/dist/hydration-markers.d.ts +8 -0
  38. package/dist/hydration-markers.js +8 -0
  39. package/dist/index.d.ts +1 -1
  40. package/dist/index.js +2 -0
  41. package/dist/runtime.d.ts +25 -40
  42. package/dist/runtime.js +254 -398
  43. package/dist/runtime.server.d.ts +23 -2
  44. package/dist/runtime.server.js +142 -36
  45. package/dist/server/index.d.ts +1 -1
  46. package/dist/server/index.js +2 -0
  47. package/dist/server/streamed-signals.js +41 -9
  48. package/dist/signals/client.js +3 -8
  49. package/dist/signals/engine.d.ts +0 -2
  50. package/dist/signals/engine.js +1 -13
  51. package/dist/universal-core.js +1 -1
  52. package/dist/version.js +1 -1
  53. package/package.json +1 -1
  54. package/dist/cjs/signals/diagnostic-local-hook.cjs +0 -37
  55. package/dist/compiler/local-void-roots.js +0 -154
  56. package/dist/signals/diagnostic-local-hook.d.ts +0 -8
  57. package/dist/signals/diagnostic-local-hook.js +0 -12
@@ -156,6 +156,7 @@ __export(runtime_server_exports, {
156
156
  ssrStylesheetResource: () => ssrStylesheetResource,
157
157
  ssrText: () => ssrText,
158
158
  ssrTextPre: () => ssrTextPre,
159
+ ssrTextSlot: () => ssrTextSlot,
159
160
  ssrTextareaValue: () => ssrTextareaValue,
160
161
  ssrTextareaValueSources: () => ssrTextareaValueSources,
161
162
  ssrTry: () => ssrTry,
@@ -205,6 +206,7 @@ var import_head_ownership = require("./head-ownership.cjs");
205
206
  var import_resource_hint_diagnostics = require("./resource-hint-diagnostics.cjs");
206
207
  var import_aria_diagnostics = require("./aria-diagnostics.cjs");
207
208
  var import_host_property_diagnostics = require("./host-property-diagnostics.cjs");
209
+ var import_hydration_markers2 = require("./hydration-markers.cjs");
208
210
  var import_early_signals = require("./server/early-signals.cjs");
209
211
  var import_shared_value_helpers = require("./shared-value-helpers.cjs");
210
212
  var import_css = require("./css.cjs");
@@ -1338,6 +1340,9 @@ function ssrText(v) {
1338
1340
  if (v == null || v === false) return "";
1339
1341
  return escapeHtml(v);
1340
1342
  }
1343
+ function ssrTextSlot(text) {
1344
+ return text === "" ? import_constants.EMPTY_COMMENT : text;
1345
+ }
1341
1346
  function ssrTextPre(v) {
1342
1347
  const s = ssrText(v);
1343
1348
  return s.charCodeAt(0) === 10 ? "\n" + s : s;
@@ -1745,13 +1750,20 @@ function ssrControl(siteKey, fn) {
1745
1750
  SIGNAL_CONTROL_SITE = previousSignalControl;
1746
1751
  }
1747
1752
  }
1748
- function enterAsyncArm(armKey, mapped = false) {
1753
+ function enterAsyncArm(armKey, mapped = false, signalSite) {
1749
1754
  const previous = ASYNC_SCOPE;
1750
1755
  const frame = FRAME;
1751
1756
  const occurrence = frame === null ? 0 : nextFrameOccurrence(frame, "@arm-position:");
1752
1757
  const fallbackPosition = armKey !== null && (typeof armKey === "object" || typeof armKey === "function" || typeof armKey === "symbol") ? previous + "|@arm-position:" + occurrence : void 0;
1753
1758
  if (SERVER_SIGNAL_BINDINGS_POTENTIAL && SIGNAL_CONTROL_SITE.charCodeAt(0) === 102) {
1754
- SIGNAL_LIST_KEYS = { parent: SIGNAL_LIST_KEYS, key: armKey, mapped, values: null };
1759
+ SIGNAL_LIST_KEYS = {
1760
+ parent: SIGNAL_LIST_KEYS,
1761
+ key: armKey,
1762
+ mapped,
1763
+ signalSite,
1764
+ position: occurrence,
1765
+ values: null
1766
+ };
1755
1767
  }
1756
1768
  ASYNC_SCOPE = previous + "|@arm:" + asyncIdentityKey(armKey, false, fallbackPosition);
1757
1769
  }
@@ -1766,18 +1778,47 @@ function ssrArm(armKey, fn) {
1766
1778
  SIGNAL_LIST_KEYS = previousSignalKeys;
1767
1779
  }
1768
1780
  }
1769
- function ssrForItem(armKey, fn, item, index, scope, block, mapped = false) {
1781
+ function ssrForItem(armKey, fn, item, index, scope, block, mapped = false, signalSite) {
1770
1782
  const previous = ASYNC_SCOPE;
1771
1783
  const previousSignalKeys = SIGNAL_LIST_KEYS;
1784
+ const previousSignalOwnerActive = SERVER_SIGNAL_OWNER_ACTIVE;
1785
+ let previousOwner;
1772
1786
  try {
1773
- enterAsyncArm(armKey, mapped);
1774
- const html = index === void 0 ? fn(item, scope) : fn(item, index, scope);
1787
+ enterAsyncArm(armKey, mapped, signalSite);
1788
+ const owner = signalSite !== void 0 && RESOLVED !== null && (SERVER_SIGNAL_BINDINGS_ENABLED || RESOLVED.signalOwner !== void 0) ? serverSignalOwner(FRAME, serverStructuralSignalInstanceKey(signalSite, void 0)) : void 0;
1789
+ let html;
1790
+ if (owner === void 0) {
1791
+ html = index === void 0 ? fn(item, scope) : fn(item, index, scope);
1792
+ } else {
1793
+ SERVER_SIGNAL_OWNER_ACTIVE = true;
1794
+ const injection = RESOLVED?.resourceOptions?.injection;
1795
+ if (injection?.observeSignalAttempt !== void 0 || (previousOwner = (0, import_owner_context.enterSynchronousSignalOwner)(owner)) === void 0) {
1796
+ html = invokeServerSignalForItem(owner, fn, item, index, scope);
1797
+ } else {
1798
+ html = index === void 0 ? fn(item, scope) : fn(item, index, scope);
1799
+ }
1800
+ }
1775
1801
  return block ? ssrBlock(html) : html;
1776
1802
  } finally {
1803
+ if (previousOwner !== void 0) (0, import_owner_context.restoreSynchronousSignalOwner)(previousOwner);
1804
+ SERVER_SIGNAL_OWNER_ACTIVE = previousSignalOwnerActive;
1777
1805
  ASYNC_SCOPE = previous;
1778
1806
  SIGNAL_LIST_KEYS = previousSignalKeys;
1779
1807
  }
1780
1808
  }
1809
+ function invokeServerSignalForItem(owner, fn, item, index, scope) {
1810
+ const invoke = () => index === void 0 ? fn(item, scope) : fn(item, index, scope);
1811
+ const injection = RESOLVED?.resourceOptions?.injection;
1812
+ return (0, import_owner_context.runWithSignalOwner)(
1813
+ owner,
1814
+ () => injection?.observeSignalAttempt === void 0 ? invoke() : (0, import_query_attempt_observer.runWithServerSignalQueryAttemptObserver)(
1815
+ owner,
1816
+ (attempt) => injection.observeSignalAttempt(attempt, (0, import_owner_context.captureSignalOwner)(owner)),
1817
+ injection.createSignalAttemptObservations,
1818
+ invoke
1819
+ )
1820
+ );
1821
+ }
1781
1822
  function ssrPortal() {
1782
1823
  return import_constants.EMPTY_COMMENT;
1783
1824
  }
@@ -2812,18 +2853,60 @@ function replayUpdatedComponentBody(comp, props, scope, frame, hp, snapshot, war
2812
2853
  } while (hp.update);
2813
2854
  return out;
2814
2855
  }
2815
- function signalIdentityKey(value) {
2856
+ function signalIdentityToken(value, position) {
2816
2857
  if (value === null) return "null";
2817
2858
  const kind = typeof value;
2818
- return kind === "string" || kind === "number" || kind === "bigint" || kind === "boolean" ? kind.charCodeAt(0).toString(36) + ":" + String(value) : kind === "undefined" ? "u:" : "o:" + String(value);
2859
+ return kind === "string" || kind === "number" || kind === "bigint" || kind === "boolean" ? kind.charCodeAt(0).toString(36) + ":" + String(value) : kind === "undefined" ? "u:" : { value, position };
2819
2860
  }
2820
- function serverStructuralSignalInstanceKey(invocationSite, key) {
2821
- return resolveServerSignalInstanceKey(SIGNAL_COMPONENT_INSTANCE_KEY) + JSON.stringify([
2861
+ function signalIdentityKey(token, base, site, parents, componentKey) {
2862
+ if (typeof token === "string") return token;
2863
+ const resolved = RESOLVED;
2864
+ const namespace = base + JSON.stringify([site ?? "legacy", parents, componentKey]);
2865
+ const namespaces = resolved.signalIdentityKeys ??= /* @__PURE__ */ new Map();
2866
+ let keys = namespaces.get(namespace);
2867
+ if (keys === void 0) {
2868
+ keys = { ids: /* @__PURE__ */ new Map(), used: /* @__PURE__ */ new Set(), next: 0 };
2869
+ namespaces.set(namespace, keys);
2870
+ }
2871
+ const value = asyncIdentityKey(token.value, false);
2872
+ let id = keys.ids.get(value);
2873
+ if (id === void 0) {
2874
+ id = token.position;
2875
+ if (id === void 0 || keys.used.has(id)) {
2876
+ while (keys.used.has(keys.next)) keys.next++;
2877
+ id = keys.next++;
2878
+ }
2879
+ keys.used.add(id);
2880
+ keys.ids.set(value, id);
2881
+ }
2882
+ return "o:" + id.toString(36);
2883
+ }
2884
+ function serverSignalSegmentKey(base, invocationSite, listKeys, key) {
2885
+ const tokens = resolveServerSignalListKeys(listKeys);
2886
+ let itemKeys = tokens;
2887
+ for (const token of tokens) {
2888
+ if (typeof token === "string") continue;
2889
+ const values = [];
2890
+ for (const entry of tokens) {
2891
+ values.push(signalIdentityKey(entry, base, invocationSite, values, false));
2892
+ }
2893
+ itemKeys = values;
2894
+ break;
2895
+ }
2896
+ return base + JSON.stringify([
2822
2897
  invocationSite ?? "legacy",
2823
- resolveServerSignalListKeys(SIGNAL_LIST_KEYS),
2824
- key != null ? signalIdentityKey(key) : ""
2898
+ itemKeys,
2899
+ key != null ? signalIdentityKey(signalIdentityToken(key), base, invocationSite, itemKeys, true) : ""
2825
2900
  ]);
2826
2901
  }
2902
+ function serverStructuralSignalInstanceKey(invocationSite, key) {
2903
+ return serverSignalSegmentKey(
2904
+ resolveServerSignalInstanceKey(SIGNAL_COMPONENT_INSTANCE_KEY),
2905
+ invocationSite,
2906
+ SIGNAL_LIST_KEYS,
2907
+ key
2908
+ );
2909
+ }
2827
2910
  function resolveServerSignalListKeys(keys) {
2828
2911
  if (keys === null) return EMPTY_SIGNAL_LIST_KEYS;
2829
2912
  if (keys.values !== null) return keys.values;
@@ -2836,7 +2919,10 @@ function resolveServerSignalListKeys(keys) {
2836
2919
  let values = parent?.values ?? EMPTY_SIGNAL_LIST_KEYS;
2837
2920
  for (let index = pending.length - 1; index >= 0; index--) {
2838
2921
  const entry = pending[index];
2839
- values = [...values, signalIdentityKey(entry.mapped ? "k" + String(entry.key) : entry.key)];
2922
+ values = [
2923
+ ...values,
2924
+ signalIdentityToken(entry.mapped ? "k" + String(entry.key) : entry.key, entry.position)
2925
+ ];
2840
2926
  entry.values = values;
2841
2927
  }
2842
2928
  return values;
@@ -2855,23 +2941,27 @@ function resolveServerSignalInstanceKey(identity) {
2855
2941
  }
2856
2942
  for (let index = pending.length - 1; index >= 0; index--) {
2857
2943
  const frame = pending[index];
2858
- identity += JSON.stringify([
2859
- frame.signalInvocationSite ?? "legacy",
2860
- resolveServerSignalListKeys(frame.signalListKeys ?? null),
2861
- frame.signalKey != null ? signalIdentityKey(frame.signalKey) : ""
2862
- ]);
2944
+ identity = serverSignalSegmentKey(
2945
+ identity,
2946
+ frame.signalInvocationSite,
2947
+ frame.signalListKeys ?? null,
2948
+ frame.signalKey
2949
+ );
2863
2950
  frame.signalInstanceKey = identity;
2864
2951
  }
2865
2952
  return identity;
2866
2953
  }
2867
- function serverSignalOwner(_frame) {
2954
+ function serverSignalOwner(_frame, rowInstanceKey) {
2868
2955
  const resolved = RESOLVED;
2869
2956
  if (resolved !== null && SERVER_SIGNAL_BINDINGS_ENABLED && resolved.signalOwner === void 0) {
2870
2957
  ensureServerSignalOwner();
2871
2958
  }
2872
2959
  if (resolved === null || resolved.signalOwner === void 0 || resolved.signalInstances === void 0)
2873
2960
  return;
2874
- const instanceKey = resolveServerSignalInstanceKey(SIGNAL_COMPONENT_INSTANCE_KEY) || JSON.stringify([SIGNAL_INSTANCE_PREFIX, "root"]);
2961
+ if (rowInstanceKey === void 0 && SIGNAL_LIST_KEYS?.signalSite !== void 0) {
2962
+ rowInstanceKey = serverStructuralSignalInstanceKey(SIGNAL_LIST_KEYS.signalSite, void 0);
2963
+ }
2964
+ const instanceKey = (rowInstanceKey ?? resolveServerSignalInstanceKey(SIGNAL_COMPONENT_INSTANCE_KEY)) || JSON.stringify([SIGNAL_INSTANCE_PREFIX, "root"]);
2875
2965
  let owner = resolved.signalInstances.get(instanceKey);
2876
2966
  if (owner === void 0) {
2877
2967
  owner = Object.freeze({
@@ -3028,7 +3118,7 @@ function renderComponentFramed(comp, props, parent, frame, inherit, instanceKey,
3028
3118
  function ssrComponent(parent, comp, props, inherit, key, identityScoped, invocationSite, bindingMarker) {
3029
3119
  const activity = comp === Activity;
3030
3120
  if (activity && key === void 0) key = props?.key;
3031
- let signalInstanceKey = SERVER_SIGNAL_BINDINGS_ENABLED ? serverStructuralSignalInstanceKey(invocationSite, key) : void 0;
3121
+ let signalInstanceKey = SERVER_SIGNAL_BINDINGS_ENABLED && RESOLVED !== null ? serverStructuralSignalInstanceKey(invocationSite, key) : void 0;
3032
3122
  const previousIdentityScope = ASYNC_SCOPE;
3033
3123
  if (identityScoped !== true) {
3034
3124
  ASYNC_SCOPE = previousIdentityScope + "|@component-type:" + asyncIdentityKey(comp, false);
@@ -3147,6 +3237,10 @@ function streamTokenForPendingHtml(html) {
3147
3237
  function ssrIndependentHydrateSidecar(props, instanceId) {
3148
3238
  const independent = props.__independent;
3149
3239
  if (independent === void 0) return "";
3240
+ const when = typeof props.when === "function" ? "dynamic" : props.when?._t;
3241
+ if (when === "dynamic" || when === "condition") {
3242
+ throw new Error((0, import_error_codes_server_generated.formatServerError)(80, when));
3243
+ }
3150
3244
  const registry = RESOLVED?.resourceOptions?.independentHydration;
3151
3245
  if (registry === void 0) {
3152
3246
  throw new Error((0, import_error_codes_server_generated.formatServerError)(69));
@@ -3188,7 +3282,23 @@ function withServerIndependentIdentity(prefix, idSeed, render) {
3188
3282
  ID_COUNTER = previousIdCounter + ID_COUNTER - idSeed;
3189
3283
  }
3190
3284
  }
3191
- function ssrHydrateAttrs(id, when, idCount, permanentStaticAncestor = false, streamToken = null) {
3285
+ function ssrIndependentStrategyAttrs(strategy) {
3286
+ const params = strategy._p;
3287
+ if (strategy._t === "media") return ssrAttr(import_hydration_markers2.HYDRATE_MEDIA_ATTR, params, "div");
3288
+ if (params === null || typeof params !== "object") return "";
3289
+ if (strategy._t === "idle") {
3290
+ const { timeout } = params;
3291
+ return timeout === void 0 ? "" : ssrAttr(import_hydration_markers2.HYDRATE_IDLE_TIMEOUT_ATTR, timeout, "div");
3292
+ }
3293
+ if (strategy._t !== "visible") return "";
3294
+ const { rootMargin, threshold } = params;
3295
+ return (rootMargin === void 0 ? "" : ssrAttr(import_hydration_markers2.HYDRATE_VISIBLE_MARGIN_ATTR, rootMargin, "div")) + (threshold === void 0 ? "" : ssrAttr(
3296
+ import_hydration_markers2.HYDRATE_VISIBLE_THRESHOLD_ATTR,
3297
+ Array.isArray(threshold) ? threshold.join(",") : threshold,
3298
+ "div"
3299
+ ));
3300
+ }
3301
+ function ssrHydrateAttrs(id, when, idCount, permanentStaticAncestor = false, streamToken = null, independent = false) {
3192
3302
  const direct = typeof when !== "function" && when !== null ? when : null;
3193
3303
  let attrs = ssrAttr(import_constants.HYDRATE_ID_ATTR, id, "div") + ssrAttr(
3194
3304
  import_constants.HYDRATE_WHEN_ATTR,
@@ -3197,6 +3307,7 @@ function ssrHydrateAttrs(id, when, idCount, permanentStaticAncestor = false, str
3197
3307
  ) + ssrAttr(import_constants.HYDRATE_ID_COUNT_ATTR, idCount, "div");
3198
3308
  if (streamToken !== null) attrs += ssrAttr(import_constants.HYDRATE_STREAM_TOKEN_ATTR, streamToken, "div");
3199
3309
  if (permanentStaticAncestor) return attrs;
3310
+ if (independent && direct !== null) attrs += ssrIndependentStrategyAttrs(direct);
3200
3311
  const strategyAttrs = direct?._a?.();
3201
3312
  if (strategyAttrs === void 0) return attrs;
3202
3313
  for (const name of Object.keys(strategyAttrs)) {
@@ -3290,7 +3401,8 @@ const hydrate = /* @__PURE__ */ (0, import_component_flags.markComponentFlags)(
3290
3401
  props.when,
3291
3402
  idCount,
3292
3403
  permanentStaticAncestor,
3293
- streamTokenForPendingHtml(children)
3404
+ streamTokenForPendingHtml(children),
3405
+ props.__independent !== void 0
3294
3406
  );
3295
3407
  const seedJson = permanentStaticAncestor || childSeeds.length === 0 ? null : serializeSuspenseSeedJson(childSeeds);
3296
3408
  const seedSidecar = seedJson === null || seedJson === "[]" ? "" : '<script type="application/json" ' + import_constants.HYDRATE_SEED_ATTR + NONCE_ATTR + ">" + seedJson + "</script>";
@@ -3711,19 +3823,7 @@ function createContext(defaultValue) {
3711
3823
  ctx.defaultValue = defaultValue;
3712
3824
  (0, import_context_identity.registerContext)(ctx);
3713
3825
  if (process.env.NODE_ENV !== "production") {
3714
- let consumerWarned = false;
3715
- Object.defineProperty(ctx, "Consumer", {
3716
- configurable: true,
3717
- get() {
3718
- if (!consumerWarned) {
3719
- consumerWarned = true;
3720
- console.error(
3721
- "Octane has no Context.Consumer. Read the context directly with use(Context) or useContext(Context) in the child component \u2014 Octane hooks are call-site keyed, so the read is legal behind any condition the render-prop form was working around."
3722
- );
3723
- }
3724
- return void 0;
3725
- }
3726
- });
3826
+ (0, import_context_identity.defineRemovedContextMembers)(ctx);
3727
3827
  }
3728
3828
  return ctx;
3729
3829
  }
@@ -4924,6 +5024,7 @@ function releaseServerRenderResources(resolved) {
4924
5024
  for (const owner of resolved.signalInstances.values()) (0, import_owner_context.retireSignalOwnerIdentity)(owner);
4925
5025
  resolved.signalInstances.clear();
4926
5026
  }
5027
+ resolved.signalIdentityKeys?.clear();
4927
5028
  if (resolved.ownedSignalOwner && resolved.signalOwner !== void 0) {
4928
5029
  (0, import_owner_context.retireSignalOwnerIdentity)(resolved.signalOwner);
4929
5030
  }
@@ -7864,6 +7965,7 @@ function preinitModule(href, options) {
7864
7965
  ssrStylesheetResource,
7865
7966
  ssrText,
7866
7967
  ssrTextPre,
7968
+ ssrTextSlot,
7867
7969
  ssrTextareaValue,
7868
7970
  ssrTextareaValueSources,
7869
7971
  ssrTry,
@@ -137,6 +137,7 @@ __export(server_exports, {
137
137
  ssrStylesheetResource: () => import_runtime_server.ssrStylesheetResource,
138
138
  ssrText: () => import_runtime_server.ssrText,
139
139
  ssrTextPre: () => import_runtime_server.ssrTextPre,
140
+ ssrTextSlot: () => import_runtime_server.ssrTextSlot,
140
141
  ssrTextareaValue: () => import_runtime_server.ssrTextareaValue,
141
142
  ssrTextareaValueSources: () => import_runtime_server.ssrTextareaValueSources,
142
143
  ssrTry: () => import_runtime_server.ssrTry,
@@ -315,6 +316,7 @@ var import_runtime_server = require("../runtime.server.cjs");
315
316
  ssrStylesheetResource,
316
317
  ssrText,
317
318
  ssrTextPre,
319
+ ssrTextSlot,
318
320
  ssrTextareaValue,
319
321
  ssrTextareaValueSources,
320
322
  ssrTry,
@@ -49,23 +49,54 @@ function limits(options) {
49
49
  function isAsyncIterable(value) {
50
50
  return value !== null && (typeof value === "object" || typeof value === "function") && typeof value[Symbol.asyncIterator] === "function";
51
51
  }
52
- async function* createStreamedSignalResultFrames(identity, result, options = {}) {
52
+ const CANCELLED = /* @__PURE__ */ Symbol("octane.streamedSignalResultCancelled");
53
+ function createStreamedSignalResultFrames(identity, result, options = {}) {
54
+ let cancelled = false;
55
+ let reject;
56
+ const waits = {
57
+ wait(value) {
58
+ if (cancelled) return Promise.reject(CANCELLED);
59
+ return new Promise((resolve, fail) => {
60
+ reject = fail;
61
+ Promise.resolve(value).then(resolve, fail);
62
+ });
63
+ },
64
+ interrupt(reason) {
65
+ const fail = reject;
66
+ reject = void 0;
67
+ fail?.(reason);
68
+ }
69
+ };
70
+ const frames = produceStreamedSignalResultFrames(identity, result, options, waits);
71
+ const returnFrames = frames.return;
72
+ frames.return = (value) => {
73
+ cancelled = true;
74
+ waits.interrupt(CANCELLED);
75
+ return returnFrames.call(frames, value);
76
+ };
77
+ return frames;
78
+ }
79
+ async function* produceStreamedSignalResultFrames(identity, result, options, waits) {
53
80
  if (!(0, import_streamed_signals_protocol.isStreamFrameIdentity)(identity)) throw new TypeError("Invalid streamed signal identity.");
54
81
  let sequence = 0;
55
82
  let resource = "promise";
56
83
  let iterator;
57
84
  const run = options.run ?? ((callback) => callback());
85
+ const signal = options.signal;
86
+ const abort = () => waits.interrupt(signal.reason);
87
+ signal?.addEventListener("abort", abort, { once: true });
58
88
  try {
59
- const resolved = await result;
60
- options.signal?.throwIfAborted();
89
+ signal?.throwIfAborted();
90
+ const resolved = await waits.wait(result);
91
+ signal?.throwIfAborted();
61
92
  if (isAsyncIterable(resolved)) {
62
93
  resource = "stream";
63
94
  iterator = run(() => resolved[Symbol.asyncIterator]());
64
95
  yield { identity, sequence: sequence++, channel: "result", kind: "open", resource: "stream" };
65
96
  for (; ; ) {
66
- options.signal?.throwIfAborted();
67
- const next = await run(() => iterator.next());
68
- options.signal?.throwIfAborted();
97
+ signal?.throwIfAborted();
98
+ const next = await waits.wait(run(() => iterator.next()));
99
+ signal?.throwIfAborted();
69
100
  if (next.done) break;
70
101
  yield {
71
102
  identity,
@@ -93,12 +124,14 @@ async function* createStreamedSignalResultFrames(identity, result, options = {})
93
124
  };
94
125
  }
95
126
  yield { identity, sequence, channel: "result", kind: "complete" };
96
- } catch {
127
+ } catch (error) {
128
+ if (error === CANCELLED) return;
97
129
  if (sequence === 0) {
98
130
  yield { identity, sequence: sequence++, channel: "result", kind: "open", resource };
99
131
  }
100
132
  yield { identity, sequence, channel: "result", kind: "error", code: "SERVER_RESULT_FAILED" };
101
133
  } finally {
134
+ signal?.removeEventListener("abort", abort);
102
135
  if (iterator !== void 0) {
103
136
  try {
104
137
  await run(() => iterator.return?.());
@@ -469,12 +502,11 @@ function createAutomaticStreamedSignalInjection(options, external) {
469
502
  attempt.release();
470
503
  return;
471
504
  }
505
+ observedAttempts.add(attemptKey);
472
506
  if (children.size >= 256) {
473
507
  attempt.release();
474
- fail(new Error("Automatic streamed signals exceeded their channel budget."));
475
508
  return;
476
509
  }
477
- observedAttempts.add(attemptKey);
478
510
  hasSignalAttempts = true;
479
511
  const identity = {
480
512
  protocol: 1,
@@ -24,7 +24,6 @@ __export(client_exports, {
24
24
  module.exports = __toCommonJS(client_exports);
25
25
  __reExport(client_exports, require("./index.cjs"), module.exports);
26
26
  var import_runtime = require("../runtime.cjs");
27
- var import_diagnostic_local_hook = require("./diagnostic-local-hook.cjs");
28
27
  var import_engine = require("./engine.cjs");
29
28
  function disposeLocalSignal(cell) {
30
29
  cell.scope.dispose();
@@ -38,11 +37,7 @@ function useSignal$(initial, slot) {
38
37
  return { scope, signal$: scope.signal$("value", value) };
39
38
  },
40
39
  disposeLocalSignal,
41
- slot,
42
- process.env.NODE_ENV === "production" || typeof initial === "function" || !(0, import_runtime.isNativeSignalDiagnosticProbe)() ? void 0 : (0, import_diagnostic_local_hook.createNativeSignalDiagnosticInitializer)(() => {
43
- const scope = (0, import_engine.createDiagnosticLocalScope)("octane/useSignal$");
44
- return { scope, signal$: scope.signal$("value", initial) };
45
- })
40
+ slot
46
41
  );
47
42
  return cell.signal$;
48
43
  }
@@ -24,7 +24,6 @@ __export(engine_exports, {
24
24
  bindScopeStreamedSelection: () => bindScopeStreamedSelection,
25
25
  createDeclaredSignalCell: () => createDeclaredSignalCell,
26
26
  createDerivedCellWith: () => createDerivedCellWith,
27
- createDiagnosticLocalScope: () => createDiagnosticLocalScope,
28
27
  createLocalScope: () => createLocalScope,
29
28
  createResourceCellWith: () => createResourceCellWith,
30
29
  createScope: () => createScope,
@@ -106,7 +105,6 @@ function decodeSeed(scopeKey, seed) {
106
105
  }
107
106
  return entries;
108
107
  }
109
- const DIAGNOSTIC_LOCAL_SCOPES = /* @__PURE__ */ new WeakSet();
110
108
  class ScopeImpl {
111
109
  constructor(key, options, seedable = true) {
112
110
  this.key = key;
@@ -593,8 +591,7 @@ class ScopeImpl {
593
591
  }
594
592
  dispose() {
595
593
  if (this.disposed) return;
596
- if (process.env.NODE_ENV === "production" || !DIAGNOSTIC_LOCAL_SCOPES.has(this))
597
- (0, import_graph.assertWritable)();
594
+ (0, import_graph.assertWritable)();
598
595
  (0, import_graph.signalBatch)(() => {
599
596
  this.disposed = true;
600
597
  this.lifetime++;
@@ -737,13 +734,6 @@ function createScope(options) {
737
734
  function createLocalScope(scopeKey) {
738
735
  return new ScopeImpl(scopeKey, { scopeKey }, false);
739
736
  }
740
- function createDiagnosticLocalScope(scopeKey) {
741
- if (process.env.NODE_ENV === "production" || !(0, import_read_protocol.isNativeWriteGuarded)() || (0, import_read_protocol.getNativeReadObserver)() !== null)
742
- throw new import_errors.SignalFrameError("Diagnostic local scopes require an isolated historical read.");
743
- const scope = new ScopeImpl(scopeKey, { scopeKey }, false);
744
- DIAGNOSTIC_LOCAL_SCOPES.add(scope);
745
- return scope;
746
- }
747
737
  function createDeclaredSignalCell(owner, key, initial, preferInitial = false) {
748
738
  if (!(owner instanceof ScopeImpl)) throw new TypeError("A direct signal needs an Octane scope.");
749
739
  return owner.createSignalDeclaration(key, initial, preferInitial);
@@ -786,7 +776,6 @@ function failScopeStreamedResult(owner, identity, error) {
786
776
  bindScopeStreamedSelection,
787
777
  createDeclaredSignalCell,
788
778
  createDerivedCellWith,
789
- createDiagnosticLocalScope,
790
779
  createLocalScope,
791
780
  createResourceCellWith,
792
781
  createScope,
@@ -21,7 +21,7 @@ __export(version_exports, {
21
21
  version: () => version
22
22
  });
23
23
  module.exports = __toCommonJS(version_exports);
24
- const version = "0.4.2";
24
+ const version = "0.4.3";
25
25
  // Annotate the CommonJS export names for ESM import in node:
26
26
  0 && (module.exports = {
27
27
  version
@@ -9,6 +9,7 @@
9
9
  * diagnostic before a sentinel can affect server behavior.
10
10
  */
11
11
  import { builders as b, parseModule } from '@tsrx/core';
12
+ import { inheritGeneratedOrigin } from './generated-origin.js';
12
13
  import { print as esrapPrint } from 'esrap';
13
14
  import esrapTsx from 'esrap/languages/tsx';
14
15
 
@@ -260,34 +261,6 @@ function collectRuntimeExports(ast, filename) {
260
261
  .sort((left, right) => (left.name < right.name ? -1 : left.name > right.name ? 1 : 0));
261
262
  }
262
263
 
263
- /**
264
- * Generated stub scaffolding has no authored syntax of its own, but every
265
- * printed node still inherits a source origin so the auxiliary module carries
266
- * a useful esrap map. The tree is compiler-owned; parsed nodes are never
267
- * embedded or mutated.
268
- */
269
- function inheritGeneratedOrigin(root, origin) {
270
- const seen = new WeakSet();
271
- const visit = (value) => {
272
- if (!value || typeof value !== 'object' || seen.has(value)) return;
273
- seen.add(value);
274
- if (Array.isArray(value)) {
275
- for (const item of value) visit(item);
276
- return;
277
- }
278
- if (typeof value.type === 'string' && value.loc == null && origin?.loc != null) {
279
- value.start = origin.start;
280
- value.end = origin.end;
281
- value.loc = origin.loc;
282
- }
283
- for (const [key, child] of Object.entries(value)) {
284
- if (key !== 'loc' && key !== 'metadata') visit(child);
285
- }
286
- };
287
- visit(root);
288
- return root;
289
- }
290
-
291
264
  function createProgram(body, origin) {
292
265
  return inheritGeneratedOrigin(
293
266
  {
@@ -5,6 +5,7 @@ import {
5
5
  } from './renderer-boundaries.js';
6
6
  import { lowerUniversalRendererRegionAst } from './compile-universal.js';
7
7
  import { builders as b, clone_ast_node, parseModule } from '@tsrx/core';
8
+ import { inheritGeneratedOrigin } from './generated-origin.js';
8
9
 
9
10
  const DOM_RENDERER = Object.freeze({ id: 'dom', module: 'octane', target: 'dom' });
10
11
  const AUTO_RUNTIME_HOOKS = new Set([
@@ -32,28 +33,6 @@ const AUTO_RUNTIME_HOOKS = new Set([
32
33
  ]);
33
34
  const AST_SKIP_KEYS = new Set(['end', 'loc', 'metadata', 'parent', 'range', 'start']);
34
35
 
35
- function inheritGeneratedOrigin(root, origin) {
36
- const seen = new WeakSet();
37
- const visit = (value) => {
38
- if (!value || typeof value !== 'object' || seen.has(value)) return;
39
- seen.add(value);
40
- if (Array.isArray(value)) {
41
- for (const item of value) visit(item);
42
- return;
43
- }
44
- if (typeof value.type === 'string' && value.loc == null && origin?.loc != null) {
45
- value.start = origin.start;
46
- value.end = origin.end;
47
- value.loc = origin.loc;
48
- }
49
- for (const [key, child] of Object.entries(value)) {
50
- if (!AST_SKIP_KEYS.has(key)) visit(child);
51
- }
52
- };
53
- visit(root);
54
- return root;
55
- }
56
-
57
36
  function mapAstCow(value, replace) {
58
37
  if (!value || typeof value !== 'object') return value;
59
38
  if (Array.isArray(value)) {
@@ -10,6 +10,7 @@
10
10
  import { builders as b, clone_ast_node, parseModule } from '@tsrx/core';
11
11
  import { normalizeUniversalRuntime } from './universal-runtime.js';
12
12
  import { createContextSourceFacts } from './context-provider.js';
13
+ import { inheritGeneratedOrigin } from './generated-origin.js';
13
14
 
14
15
  // Keep this catalogue in the compiler, never in generated application code. It
15
16
  // is the union of actual constructor exports from Three r156, r172, and r183,
@@ -402,28 +403,6 @@ function withPlanOrigin(value, origin) {
402
403
  return value;
403
404
  }
404
405
 
405
- function inheritGeneratedOrigin(root, origin) {
406
- const seen = new WeakSet();
407
- const visit = (value) => {
408
- if (!value || typeof value !== 'object' || seen.has(value)) return;
409
- seen.add(value);
410
- if (Array.isArray(value)) {
411
- for (const item of value) visit(item);
412
- return;
413
- }
414
- if (typeof value.type === 'string' && value.loc == null && origin?.loc != null) {
415
- value.start = origin.start;
416
- value.end = origin.end;
417
- value.loc = origin.loc;
418
- }
419
- for (const [key, child] of Object.entries(value)) {
420
- if (!AST_SKIP_KEYS.has(key)) visit(child);
421
- }
422
- };
423
- visit(root);
424
- return root;
425
- }
426
-
427
406
  function jsonValueToAst(value, origin) {
428
407
  const valueOrigin =
429
408
  value && typeof value === 'object' && value[PLAN_ORIGIN] ? value[PLAN_ORIGIN] : origin;