octane 0.4.1 → 0.4.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.
@@ -158,6 +158,7 @@ __export(runtime_exports, {
158
158
  isChildrenBlock: () => isChildrenBlock,
159
159
  isHydratingStyle: () => isHydratingStyle,
160
160
  isInActScope: () => isInActScope,
161
+ isNativeSignalDiagnosticProbe: () => isNativeSignalDiagnosticProbe,
161
162
  isValidElement: () => isValidElement,
162
163
  keyedForBlock: () => keyedForBlock,
163
164
  lazy: () => lazy,
@@ -357,6 +358,7 @@ var import_transition_state = require("./signals/transition-state.cjs");
357
358
  var import_transition_candidate = require("./signals/transition-candidate.cjs");
358
359
  var import_read_protocol = require("./signals/read-protocol.cjs");
359
360
  var import_native_read_events = require("./signals/native-read-events.cjs");
361
+ var import_diagnostic_local_hook = require("./signals/diagnostic-local-hook.cjs");
360
362
  var import_native_read_seeds = require("./signals/native-read-seeds.cjs");
361
363
  var import_owner_context = require("./signals/owner-context.cjs");
362
364
  var import_document_owner = require("./signals/document-owner.cjs");
@@ -833,12 +835,12 @@ function nativePresentationBinding(owner, slotIndex, el, body, props) {
833
835
  }
834
836
  function enableNativeReadCollection(abi = 1) {
835
837
  if (abi !== 1) throw new Error((0, import_error_codes_client_generated.formatClientError)(58));
838
+ if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return;
836
839
  ensureNativeReadDriver();
837
840
  }
838
841
  function beginNativeReadScope(scope, abi = 1) {
839
- if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null)
840
- throw new PresentationAdoptionMiss(void 0, false);
841
842
  if (abi !== 1) throw new Error((0, import_error_codes_client_generated.formatClientError)(58));
843
+ if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return -1;
842
844
  const block = CURRENT_BLOCK;
843
845
  const owner = scope ?? CURRENT_SCOPE;
844
846
  if (block === null || owner === null) return -1;
@@ -954,12 +956,14 @@ function endNativeReadScope(token, _completed) {
954
956
  if (token >= 0) NATIVE_READ_DRIVER.endScope(token);
955
957
  }
956
958
  function beginNativeReadWitness(detached = false) {
959
+ if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return -1;
957
960
  return detached ? ensureNativeReadDriver().beginWitness(true) : NATIVE_READ_DRIVER?.beginWitness() ?? -1;
958
961
  }
959
962
  function finishNativeReadWitness(token, completed) {
960
963
  return token < 0 ? null : NATIVE_READ_DRIVER.finishWitness(token, completed);
961
964
  }
962
965
  function replayNativeReadWitness(witness) {
966
+ if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return;
963
967
  NATIVE_READ_DRIVER?.replay(witness);
964
968
  }
965
969
  function retainNativeRetryReads(block, reads) {
@@ -6789,7 +6793,8 @@ function renderBlockInner(block) {
6789
6793
  let profileThrown;
6790
6794
  let renderCompleted = false;
6791
6795
  let renderRetry = false;
6792
- NATIVE_READ_DRIVER?.beginRender(block);
6796
+ if (process.env.NODE_ENV === "production" || hydrateAttributeProbe === null)
6797
+ NATIVE_READ_DRIVER?.beginRender(block);
6793
6798
  NATIVE_BLOCK_RETRIES?.get(block)?.clear();
6794
6799
  try {
6795
6800
  if (urgentTransitionRender !== null)
@@ -6857,7 +6862,8 @@ function renderBlockInner(block) {
6857
6862
  CURRENT_SCOPE = prevScope;
6858
6863
  CURRENT_BLOCK = prevBlock;
6859
6864
  try {
6860
- NATIVE_READ_DRIVER?.endRender(block, renderCompleted, isSuspenseException(profileThrown));
6865
+ if (process.env.NODE_ENV === "production" || hydrateAttributeProbe === null)
6866
+ NATIVE_READ_DRIVER?.endRender(block, renderCompleted, isSuspenseException(profileThrown));
6861
6867
  } finally {
6862
6868
  if (urgentTransitionRender !== null)
6863
6869
  urgentTransitionDriver.endUrgent(block, urgentTransitionRender);
@@ -7475,15 +7481,20 @@ function resolveSlot(slot) {
7475
7481
  const resolved = (0, import_hook_slot_cache.resolveHookPath)(slotStack, slot, false);
7476
7482
  return typeof __OCTANE_PROFILE_ENABLED__ !== "undefined" && __OCTANE_PROFILE_ENABLED__ ? (0, import_profiling.__profileResolveHook)(resolved, typeof slot === "symbol" ? slot : void 0) : resolved;
7477
7483
  }
7478
- function nativeLocalHook(name, initialize, dispose, slot) {
7479
- if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null)
7484
+ function isNativeSignalDiagnosticProbe() {
7485
+ return process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null;
7486
+ }
7487
+ function nativeLocalHook(name, initialize, dispose, slot, diagnosticInitialize) {
7488
+ if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null && (name !== "useSignal$" || diagnosticInitialize === void 0 || !(0, import_diagnostic_local_hook.isNativeSignalDiagnosticInitializer)(diagnosticInitialize)))
7480
7489
  throw new PresentationAdoptionMiss(void 0, false);
7481
7490
  slot = resolveSlot(slot);
7482
7491
  if (slot === void 0 || CURRENT_SCOPE === null) missingSlot(name);
7483
7492
  const scope = CURRENT_SCOPE;
7484
7493
  let cell = scope.hooks?.get(slot);
7485
7494
  if (cell === void 0) {
7486
- cell = { nativeValue: initialize() };
7495
+ cell = {
7496
+ nativeValue: process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null ? diagnosticInitialize() : initialize()
7497
+ };
7487
7498
  ensureHooks(scope).set(slot, cell);
7488
7499
  const value = cell.nativeValue;
7489
7500
  registerHookCleanup(scope, () => dispose(value));
@@ -8941,6 +8952,7 @@ function collectInitialHydrateAttributes(state, snapshot) {
8941
8952
  if (state.seedRaw !== null) hydration.seeds = hydration.parseSeeds(state.seedRaw);
8942
8953
  hydration.protectRootAnchor(end);
8943
8954
  const capture = createOffscreenCapture();
8955
+ const diagnosticNative = state.nativeSeedRaw === void 0 ? void 0 : (0, import_native_read_seeds.createNativeAdoptionState)((0, import_native_read_seeds.parseNativeSignalManifest)(state.nativeSeedRaw));
8944
8956
  const previousHydration = currentHydration;
8945
8957
  const previousCapture = WIP_CAPTURE;
8946
8958
  const previousProbe = hydrateAttributeProbe;
@@ -8960,7 +8972,10 @@ function collectInitialHydrateAttributes(state, snapshot) {
8960
8972
  const previousSelectDefaultSyncs = SELECT_DEFAULT_SYNCS;
8961
8973
  const previousFormChecks = DEV_FORM_CHECKS;
8962
8974
  const previousAutofocus = AUTOFOCUS_QUEUE;
8963
- const previousNative = (0, import_read_protocol.setNativeAdoptionResolver)(null);
8975
+ const diagnosticDriver = NATIVE_READ_DRIVER;
8976
+ const nativeProbeToken = diagnosticDriver?.pauseLifecycle() ?? -1;
8977
+ const previousWriteGuard = (0, import_read_protocol.beginNativeWriteGuard)();
8978
+ const previousNative = (0, import_read_protocol.setNativeAdoptionResolver)(diagnosticNative?.resolve ?? null);
8964
8979
  const refDetachCheckpoint = refDetachQueue.length;
8965
8980
  currentHydration = hydration;
8966
8981
  WIP_CAPTURE = capture;
@@ -8990,27 +9005,36 @@ function collectInitialHydrateAttributes(state, snapshot) {
8990
9005
  disposeWip({ block, start, end, capture, domParent: wrapper, refDetachCheckpoint });
8991
9006
  drainHydrationRenderPhaseUpdates(block);
8992
9007
  } finally {
8993
- (0, import_read_protocol.setNativeAdoptionResolver)(previousNative);
8994
- currentHydration = previousHydration;
8995
- WIP_CAPTURE = previousCapture;
8996
- hydrateAttributeProbe = previousProbe;
8997
- ROOT_RENDER_TRANSACTION = previousTransaction;
8998
- TRANSITION_JOURNAL = previousJournal;
8999
- ACTIVE_TRANSITION_ATTEMPT = previousAttempt;
9000
- SCOPED_READ_TRACKING = previousScopedReadTracking;
9001
- SCOPED_READS = previousScopedReads;
9002
- CURRENT_WARM = previousWarm;
9003
- CURRENT_WARM_CLAIMS = previousWarmClaims;
9004
- CURRENT_WARM_EPISODE = previousWarmEpisode;
9005
- ACTIVE_WARM_PLANS.length = 0;
9006
- ACTIVE_WARM_PLANS.push(...previousWarmPlans);
9007
- STAGED_DOM = previousStagedDom;
9008
- STAGED_COMMIT_CAPTURE = previousStagedCapture;
9009
- PRESENTATION_HYDRATION = previousPresentation;
9010
- SELECT_SYNCS = previousSelectSyncs;
9011
- SELECT_DEFAULT_SYNCS = previousSelectDefaultSyncs;
9012
- DEV_FORM_CHECKS = previousFormChecks;
9013
- AUTOFOCUS_QUEUE = previousAutofocus;
9008
+ try {
9009
+ diagnosticNative?.release();
9010
+ } finally {
9011
+ try {
9012
+ (0, import_read_protocol.setNativeAdoptionResolver)(previousNative);
9013
+ (0, import_read_protocol.endNativeWriteGuard)(previousWriteGuard);
9014
+ if (nativeProbeToken >= 0) diagnosticDriver.resumeLifecycle(nativeProbeToken);
9015
+ } finally {
9016
+ currentHydration = previousHydration;
9017
+ WIP_CAPTURE = previousCapture;
9018
+ hydrateAttributeProbe = previousProbe;
9019
+ ROOT_RENDER_TRANSACTION = previousTransaction;
9020
+ TRANSITION_JOURNAL = previousJournal;
9021
+ ACTIVE_TRANSITION_ATTEMPT = previousAttempt;
9022
+ SCOPED_READ_TRACKING = previousScopedReadTracking;
9023
+ SCOPED_READS = previousScopedReads;
9024
+ CURRENT_WARM = previousWarm;
9025
+ CURRENT_WARM_CLAIMS = previousWarmClaims;
9026
+ CURRENT_WARM_EPISODE = previousWarmEpisode;
9027
+ ACTIVE_WARM_PLANS.length = 0;
9028
+ ACTIVE_WARM_PLANS.push(...previousWarmPlans);
9029
+ STAGED_DOM = previousStagedDom;
9030
+ STAGED_COMMIT_CAPTURE = previousStagedCapture;
9031
+ PRESENTATION_HYDRATION = previousPresentation;
9032
+ SELECT_SYNCS = previousSelectSyncs;
9033
+ SELECT_DEFAULT_SYNCS = previousSelectDefaultSyncs;
9034
+ DEV_FORM_CHECKS = previousFormChecks;
9035
+ AUTOFOCUS_QUEUE = previousAutofocus;
9036
+ }
9037
+ }
9014
9038
  }
9015
9039
  }
9016
9040
  return probe;
@@ -28735,6 +28759,7 @@ function scriptResource(attrs) {
28735
28759
  isChildrenBlock,
28736
28760
  isHydratingStyle,
28737
28761
  isInActScope,
28762
+ isNativeSignalDiagnosticProbe,
28738
28763
  isValidElement,
28739
28764
  keyedForBlock,
28740
28765
  lazy,
@@ -24,6 +24,7 @@ __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");
27
28
  var import_engine = require("./engine.cjs");
28
29
  function disposeLocalSignal(cell) {
29
30
  cell.scope.dispose();
@@ -37,7 +38,11 @@ function useSignal$(initial, slot) {
37
38
  return { scope, signal$: scope.signal$("value", value) };
38
39
  },
39
40
  disposeLocalSignal,
40
- slot
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
+ })
41
46
  );
42
47
  return cell.signal$;
43
48
  }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var diagnostic_local_hook_exports = {};
20
+ __export(diagnostic_local_hook_exports, {
21
+ createNativeSignalDiagnosticInitializer: () => createNativeSignalDiagnosticInitializer,
22
+ isNativeSignalDiagnosticInitializer: () => isNativeSignalDiagnosticInitializer
23
+ });
24
+ module.exports = __toCommonJS(diagnostic_local_hook_exports);
25
+ const DIAGNOSTIC_SIGNAL_INITIALIZERS = /* @__PURE__ */ new WeakSet();
26
+ function createNativeSignalDiagnosticInitializer(initialize) {
27
+ DIAGNOSTIC_SIGNAL_INITIALIZERS.add(initialize);
28
+ return initialize;
29
+ }
30
+ function isNativeSignalDiagnosticInitializer(value) {
31
+ return DIAGNOSTIC_SIGNAL_INITIALIZERS.has(value);
32
+ }
33
+ // Annotate the CommonJS export names for ESM import in node:
34
+ 0 && (module.exports = {
35
+ createNativeSignalDiagnosticInitializer,
36
+ isNativeSignalDiagnosticInitializer
37
+ });
@@ -24,6 +24,7 @@ __export(engine_exports, {
24
24
  bindScopeStreamedSelection: () => bindScopeStreamedSelection,
25
25
  createDeclaredSignalCell: () => createDeclaredSignalCell,
26
26
  createDerivedCellWith: () => createDerivedCellWith,
27
+ createDiagnosticLocalScope: () => createDiagnosticLocalScope,
27
28
  createLocalScope: () => createLocalScope,
28
29
  createResourceCellWith: () => createResourceCellWith,
29
30
  createScope: () => createScope,
@@ -105,6 +106,7 @@ function decodeSeed(scopeKey, seed) {
105
106
  }
106
107
  return entries;
107
108
  }
109
+ const DIAGNOSTIC_LOCAL_SCOPES = /* @__PURE__ */ new WeakSet();
108
110
  class ScopeImpl {
109
111
  constructor(key, options, seedable = true) {
110
112
  this.key = key;
@@ -591,7 +593,8 @@ class ScopeImpl {
591
593
  }
592
594
  dispose() {
593
595
  if (this.disposed) return;
594
- (0, import_graph.assertWritable)();
596
+ if (process.env.NODE_ENV === "production" || !DIAGNOSTIC_LOCAL_SCOPES.has(this))
597
+ (0, import_graph.assertWritable)();
595
598
  (0, import_graph.signalBatch)(() => {
596
599
  this.disposed = true;
597
600
  this.lifetime++;
@@ -734,6 +737,13 @@ function createScope(options) {
734
737
  function createLocalScope(scopeKey) {
735
738
  return new ScopeImpl(scopeKey, { scopeKey }, false);
736
739
  }
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
+ }
737
747
  function createDeclaredSignalCell(owner, key, initial, preferInitial = false) {
738
748
  if (!(owner instanceof ScopeImpl)) throw new TypeError("A direct signal needs an Octane scope.");
739
749
  return owner.createSignalDeclaration(key, initial, preferInitial);
@@ -776,6 +786,7 @@ function failScopeStreamedResult(owner, identity, error) {
776
786
  bindScopeStreamedSelection,
777
787
  createDeclaredSignalCell,
778
788
  createDerivedCellWith,
789
+ createDiagnosticLocalScope,
779
790
  createLocalScope,
780
791
  createResourceCellWith,
781
792
  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.1";
24
+ const version = "0.4.2";
25
25
  // Annotate the CommonJS export names for ESM import in node:
26
26
  0 && (module.exports = {
27
27
  version
package/dist/runtime.d.ts CHANGED
@@ -24,6 +24,7 @@ import { validateNativeReadWitness, type NativeReadWitness } from './signals/nat
24
24
  import { type NativeReadRetry } from './signals/native-read-retry.js';
25
25
  import type { SignalActionFrame } from './signals/transition-action.js';
26
26
  import { setNativeAdoptionResolver } from './signals/read-protocol.js';
27
+ import { type DiagnosticSignalInitializer } from './signals/diagnostic-local-hook.js';
27
28
  import { type NativeAdoptionState } from './signals/native-read-seeds.js';
28
29
  export { documentSignalOwner, installStreamedSignalOwnerActivator, } from './signals/document-owner.js';
29
30
  import { type SignalHandle, type SignalOwner, type SignalRendererOwnerIdentity } from './signals/types.js';
@@ -824,8 +825,10 @@ export declare function manualHook<F extends (...args: any[]) => any>(fn: F, nam
824
825
  /** Invoke a cached optional-chain method without consulting its call/bind properties. */
825
826
  export declare function callWithReceiver<T>(fn: (...args: any[]) => T, receiver: unknown, ...args: any[]): T;
826
827
  export declare function withSlot<T>(sym: symbol, fn: (...a: any[]) => T, ...args: any[]): T;
828
+ /** @internal Built-in adapters are allocated only during historical comparison. */
829
+ export declare function isNativeSignalDiagnosticProbe(): boolean;
827
830
  /** @internal Optional native hooks use the existing compiler slot and Scope lifetime. */
828
- export declare function nativeLocalHook<T>(name: string, initialize: () => T, dispose: (value: T) => void, slot?: HookSlot): T;
831
+ export declare function nativeLocalHook<T>(name: string, initialize: () => T, dispose: (value: T) => void, slot?: HookSlot, diagnosticInitialize?: DiagnosticSignalInitializer<T>): T;
829
832
  interface StateSlot<T> {
830
833
  value: T;
831
834
  setter: (next: T | ((prev: T) => T)) => void;
package/dist/runtime.js CHANGED
@@ -180,9 +180,14 @@ import {
180
180
  registerNativeActionResolver,
181
181
  runNativeBatch,
182
182
  setNativeCandidateResolver,
183
- setNativeAdoptionResolver
183
+ setNativeAdoptionResolver,
184
+ beginNativeWriteGuard,
185
+ endNativeWriteGuard
184
186
  } from "./signals/read-protocol.js";
185
187
  import { beginNativeEventBatch, endNativeEventBatch } from "./signals/native-read-events.js";
188
+ import {
189
+ isNativeSignalDiagnosticInitializer
190
+ } from "./signals/diagnostic-local-hook.js";
186
191
  import {
187
192
  createNativeAdoptionState,
188
193
  NATIVE_SIGNAL_SEED_ATTR,
@@ -686,12 +691,12 @@ function nativePresentationBinding(owner, slotIndex, el, body, props) {
686
691
  }
687
692
  function enableNativeReadCollection(abi = 1) {
688
693
  if (abi !== 1) throw new Error(formatClientError(58));
694
+ if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return;
689
695
  ensureNativeReadDriver();
690
696
  }
691
697
  function beginNativeReadScope(scope, abi = 1) {
692
- if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null)
693
- throw new PresentationAdoptionMiss(void 0, false);
694
698
  if (abi !== 1) throw new Error(formatClientError(58));
699
+ if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return -1;
695
700
  const block = CURRENT_BLOCK;
696
701
  const owner = scope ?? CURRENT_SCOPE;
697
702
  if (block === null || owner === null) return -1;
@@ -807,12 +812,14 @@ function endNativeReadScope(token, _completed) {
807
812
  if (token >= 0) NATIVE_READ_DRIVER.endScope(token);
808
813
  }
809
814
  function beginNativeReadWitness(detached = false) {
815
+ if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return -1;
810
816
  return detached ? ensureNativeReadDriver().beginWitness(true) : NATIVE_READ_DRIVER?.beginWitness() ?? -1;
811
817
  }
812
818
  function finishNativeReadWitness(token, completed) {
813
819
  return token < 0 ? null : NATIVE_READ_DRIVER.finishWitness(token, completed);
814
820
  }
815
821
  function replayNativeReadWitness(witness) {
822
+ if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null) return;
816
823
  NATIVE_READ_DRIVER?.replay(witness);
817
824
  }
818
825
  function retainNativeRetryReads(block, reads) {
@@ -6642,7 +6649,8 @@ function renderBlockInner(block) {
6642
6649
  let profileThrown;
6643
6650
  let renderCompleted = false;
6644
6651
  let renderRetry = false;
6645
- NATIVE_READ_DRIVER?.beginRender(block);
6652
+ if (process.env.NODE_ENV === "production" || hydrateAttributeProbe === null)
6653
+ NATIVE_READ_DRIVER?.beginRender(block);
6646
6654
  NATIVE_BLOCK_RETRIES?.get(block)?.clear();
6647
6655
  try {
6648
6656
  if (urgentTransitionRender !== null)
@@ -6710,7 +6718,8 @@ function renderBlockInner(block) {
6710
6718
  CURRENT_SCOPE = prevScope;
6711
6719
  CURRENT_BLOCK = prevBlock;
6712
6720
  try {
6713
- NATIVE_READ_DRIVER?.endRender(block, renderCompleted, isSuspenseException(profileThrown));
6721
+ if (process.env.NODE_ENV === "production" || hydrateAttributeProbe === null)
6722
+ NATIVE_READ_DRIVER?.endRender(block, renderCompleted, isSuspenseException(profileThrown));
6714
6723
  } finally {
6715
6724
  if (urgentTransitionRender !== null)
6716
6725
  urgentTransitionDriver.endUrgent(block, urgentTransitionRender);
@@ -7328,15 +7337,20 @@ function resolveSlot(slot) {
7328
7337
  const resolved = resolveHookPath(slotStack, slot, false);
7329
7338
  return typeof __OCTANE_PROFILE_ENABLED__ !== "undefined" && __OCTANE_PROFILE_ENABLED__ ? __profileResolveHook(resolved, typeof slot === "symbol" ? slot : void 0) : resolved;
7330
7339
  }
7331
- function nativeLocalHook(name, initialize, dispose, slot) {
7332
- if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null)
7340
+ function isNativeSignalDiagnosticProbe() {
7341
+ return process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null;
7342
+ }
7343
+ function nativeLocalHook(name, initialize, dispose, slot, diagnosticInitialize) {
7344
+ if (process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null && (name !== "useSignal$" || diagnosticInitialize === void 0 || !isNativeSignalDiagnosticInitializer(diagnosticInitialize)))
7333
7345
  throw new PresentationAdoptionMiss(void 0, false);
7334
7346
  slot = resolveSlot(slot);
7335
7347
  if (slot === void 0 || CURRENT_SCOPE === null) missingSlot(name);
7336
7348
  const scope = CURRENT_SCOPE;
7337
7349
  let cell = scope.hooks?.get(slot);
7338
7350
  if (cell === void 0) {
7339
- cell = { nativeValue: initialize() };
7351
+ cell = {
7352
+ nativeValue: process.env.NODE_ENV !== "production" && hydrateAttributeProbe !== null ? diagnosticInitialize() : initialize()
7353
+ };
7340
7354
  ensureHooks(scope).set(slot, cell);
7341
7355
  const value = cell.nativeValue;
7342
7356
  registerHookCleanup(scope, () => dispose(value));
@@ -8794,6 +8808,7 @@ function collectInitialHydrateAttributes(state, snapshot) {
8794
8808
  if (state.seedRaw !== null) hydration.seeds = hydration.parseSeeds(state.seedRaw);
8795
8809
  hydration.protectRootAnchor(end);
8796
8810
  const capture = createOffscreenCapture();
8811
+ const diagnosticNative = state.nativeSeedRaw === void 0 ? void 0 : createNativeAdoptionState(parseNativeSignalManifest(state.nativeSeedRaw));
8797
8812
  const previousHydration = currentHydration;
8798
8813
  const previousCapture = WIP_CAPTURE;
8799
8814
  const previousProbe = hydrateAttributeProbe;
@@ -8813,7 +8828,10 @@ function collectInitialHydrateAttributes(state, snapshot) {
8813
8828
  const previousSelectDefaultSyncs = SELECT_DEFAULT_SYNCS;
8814
8829
  const previousFormChecks = DEV_FORM_CHECKS;
8815
8830
  const previousAutofocus = AUTOFOCUS_QUEUE;
8816
- const previousNative = setNativeAdoptionResolver(null);
8831
+ const diagnosticDriver = NATIVE_READ_DRIVER;
8832
+ const nativeProbeToken = diagnosticDriver?.pauseLifecycle() ?? -1;
8833
+ const previousWriteGuard = beginNativeWriteGuard();
8834
+ const previousNative = setNativeAdoptionResolver(diagnosticNative?.resolve ?? null);
8817
8835
  const refDetachCheckpoint = refDetachQueue.length;
8818
8836
  currentHydration = hydration;
8819
8837
  WIP_CAPTURE = capture;
@@ -8843,27 +8861,36 @@ function collectInitialHydrateAttributes(state, snapshot) {
8843
8861
  disposeWip({ block, start, end, capture, domParent: wrapper, refDetachCheckpoint });
8844
8862
  drainHydrationRenderPhaseUpdates(block);
8845
8863
  } finally {
8846
- setNativeAdoptionResolver(previousNative);
8847
- currentHydration = previousHydration;
8848
- WIP_CAPTURE = previousCapture;
8849
- hydrateAttributeProbe = previousProbe;
8850
- ROOT_RENDER_TRANSACTION = previousTransaction;
8851
- TRANSITION_JOURNAL = previousJournal;
8852
- ACTIVE_TRANSITION_ATTEMPT = previousAttempt;
8853
- SCOPED_READ_TRACKING = previousScopedReadTracking;
8854
- SCOPED_READS = previousScopedReads;
8855
- CURRENT_WARM = previousWarm;
8856
- CURRENT_WARM_CLAIMS = previousWarmClaims;
8857
- CURRENT_WARM_EPISODE = previousWarmEpisode;
8858
- ACTIVE_WARM_PLANS.length = 0;
8859
- ACTIVE_WARM_PLANS.push(...previousWarmPlans);
8860
- STAGED_DOM = previousStagedDom;
8861
- STAGED_COMMIT_CAPTURE = previousStagedCapture;
8862
- PRESENTATION_HYDRATION = previousPresentation;
8863
- SELECT_SYNCS = previousSelectSyncs;
8864
- SELECT_DEFAULT_SYNCS = previousSelectDefaultSyncs;
8865
- DEV_FORM_CHECKS = previousFormChecks;
8866
- AUTOFOCUS_QUEUE = previousAutofocus;
8864
+ try {
8865
+ diagnosticNative?.release();
8866
+ } finally {
8867
+ try {
8868
+ setNativeAdoptionResolver(previousNative);
8869
+ endNativeWriteGuard(previousWriteGuard);
8870
+ if (nativeProbeToken >= 0) diagnosticDriver.resumeLifecycle(nativeProbeToken);
8871
+ } finally {
8872
+ currentHydration = previousHydration;
8873
+ WIP_CAPTURE = previousCapture;
8874
+ hydrateAttributeProbe = previousProbe;
8875
+ ROOT_RENDER_TRANSACTION = previousTransaction;
8876
+ TRANSITION_JOURNAL = previousJournal;
8877
+ ACTIVE_TRANSITION_ATTEMPT = previousAttempt;
8878
+ SCOPED_READ_TRACKING = previousScopedReadTracking;
8879
+ SCOPED_READS = previousScopedReads;
8880
+ CURRENT_WARM = previousWarm;
8881
+ CURRENT_WARM_CLAIMS = previousWarmClaims;
8882
+ CURRENT_WARM_EPISODE = previousWarmEpisode;
8883
+ ACTIVE_WARM_PLANS.length = 0;
8884
+ ACTIVE_WARM_PLANS.push(...previousWarmPlans);
8885
+ STAGED_DOM = previousStagedDom;
8886
+ STAGED_COMMIT_CAPTURE = previousStagedCapture;
8887
+ PRESENTATION_HYDRATION = previousPresentation;
8888
+ SELECT_SYNCS = previousSelectSyncs;
8889
+ SELECT_DEFAULT_SYNCS = previousSelectDefaultSyncs;
8890
+ DEV_FORM_CHECKS = previousFormChecks;
8891
+ AUTOFOCUS_QUEUE = previousAutofocus;
8892
+ }
8893
+ }
8867
8894
  }
8868
8895
  }
8869
8896
  return probe;
@@ -28596,6 +28623,7 @@ export {
28596
28623
  isChildrenBlock,
28597
28624
  isHydratingStyle,
28598
28625
  isInActScope,
28626
+ isNativeSignalDiagnosticProbe,
28599
28627
  isValidElement,
28600
28628
  keyedForBlock,
28601
28629
  lazy,
@@ -1,6 +1,7 @@
1
1
  export * from "./index.js";
2
- import { nativeLocalHook } from "../runtime.js";
3
- import { createLocalScope } from "./engine.js";
2
+ import { isNativeSignalDiagnosticProbe, nativeLocalHook } from "../runtime.js";
3
+ import { createNativeSignalDiagnosticInitializer } from "./diagnostic-local-hook.js";
4
+ import { createDiagnosticLocalScope, createLocalScope } from "./engine.js";
4
5
  function disposeLocalSignal(cell) {
5
6
  cell.scope.dispose();
6
7
  }
@@ -13,7 +14,11 @@ function useSignal$(initial, slot) {
13
14
  return { scope, signal$: scope.signal$("value", value) };
14
15
  },
15
16
  disposeLocalSignal,
16
- slot
17
+ slot,
18
+ process.env.NODE_ENV === "production" || typeof initial === "function" || !isNativeSignalDiagnosticProbe() ? void 0 : createNativeSignalDiagnosticInitializer(() => {
19
+ const scope = createDiagnosticLocalScope("octane/useSignal$");
20
+ return { scope, signal$: scope.signal$("value", initial) };
21
+ })
17
22
  );
18
23
  return cell.signal$;
19
24
  }
@@ -0,0 +1,8 @@
1
+ declare const DIAGNOSTIC_SIGNAL_INITIALIZER: unique symbol;
2
+ export type DiagnosticSignalInitializer<T> = (() => T) & {
3
+ readonly [DIAGNOSTIC_SIGNAL_INITIALIZER]: true;
4
+ };
5
+ /** @internal Private built-in useSignal$ adapter; not a public native-hook resource factory. */
6
+ export declare function createNativeSignalDiagnosticInitializer<T>(initialize: () => T): DiagnosticSignalInitializer<T>;
7
+ export declare function isNativeSignalDiagnosticInitializer(value: () => unknown): boolean;
8
+ export {};
@@ -0,0 +1,12 @@
1
+ const DIAGNOSTIC_SIGNAL_INITIALIZERS = /* @__PURE__ */ new WeakSet();
2
+ function createNativeSignalDiagnosticInitializer(initialize) {
3
+ DIAGNOSTIC_SIGNAL_INITIALIZERS.add(initialize);
4
+ return initialize;
5
+ }
6
+ function isNativeSignalDiagnosticInitializer(value) {
7
+ return DIAGNOSTIC_SIGNAL_INITIALIZERS.has(value);
8
+ }
9
+ export {
10
+ createNativeSignalDiagnosticInitializer,
11
+ isNativeSignalDiagnosticInitializer
12
+ };
@@ -105,6 +105,8 @@ declare class AdoptionFrameImpl implements AdoptionFrame {
105
105
  export declare function createScope(options: ScopeOptions): Scope;
106
106
  /** Only the native hook adapter may create a component-owned, non-serializable scope. */
107
107
  export declare function createLocalScope(scopeKey: string): Scope;
108
+ /** @internal Isolated historical useSignal$ state, never a live presentation cell. */
109
+ export declare function createDiagnosticLocalScope(scopeKey: string): Scope;
108
110
  export declare function createDeclaredSignalCell<T>(owner: Scope, key: string, initial: T, preferInitial?: boolean): WritableSignal<T>;
109
111
  export declare function createDerivedCellWith<T>(owner: Scope, key: string, compute: DerivedCompute<T>, options: DerivedOptions | undefined, Binding: DerivedBindingFactory<T>): DerivedSignal<T>;
110
112
  export declare function createResourceCellWith<T>(owner: Scope, key: string, describe: () => QueryRequest<T> | typeof skip, initialize: typeof initializeResource, unique?: boolean): Resource<T>;
@@ -30,6 +30,8 @@ import {
30
30
  beginNativeWriteGuard,
31
31
  endNativeWriteGuard,
32
32
  getNativeAdoptionResolver,
33
+ getNativeReadObserver,
34
+ isNativeWriteGuarded,
33
35
  registerNativeBatchHooks,
34
36
  reportNativeRead
35
37
  } from "./read-protocol.js";
@@ -99,6 +101,7 @@ function decodeSeed(scopeKey, seed) {
99
101
  }
100
102
  return entries;
101
103
  }
104
+ const DIAGNOSTIC_LOCAL_SCOPES = /* @__PURE__ */ new WeakSet();
102
105
  class ScopeImpl {
103
106
  constructor(key, options, seedable = true) {
104
107
  this.key = key;
@@ -585,7 +588,8 @@ class ScopeImpl {
585
588
  }
586
589
  dispose() {
587
590
  if (this.disposed) return;
588
- assertWritable();
591
+ if (process.env.NODE_ENV === "production" || !DIAGNOSTIC_LOCAL_SCOPES.has(this))
592
+ assertWritable();
589
593
  signalBatch(() => {
590
594
  this.disposed = true;
591
595
  this.lifetime++;
@@ -728,6 +732,13 @@ function createScope(options) {
728
732
  function createLocalScope(scopeKey) {
729
733
  return new ScopeImpl(scopeKey, { scopeKey }, false);
730
734
  }
735
+ function createDiagnosticLocalScope(scopeKey) {
736
+ if (process.env.NODE_ENV === "production" || !isNativeWriteGuarded() || getNativeReadObserver() !== null)
737
+ throw new SignalFrameError("Diagnostic local scopes require an isolated historical read.");
738
+ const scope = new ScopeImpl(scopeKey, { scopeKey }, false);
739
+ DIAGNOSTIC_LOCAL_SCOPES.add(scope);
740
+ return scope;
741
+ }
731
742
  function createDeclaredSignalCell(owner, key, initial, preferInitial = false) {
732
743
  if (!(owner instanceof ScopeImpl)) throw new TypeError("A direct signal needs an Octane scope.");
733
744
  return owner.createSignalDeclaration(key, initial, preferInitial);
@@ -769,6 +780,7 @@ export {
769
780
  bindScopeStreamedSelection,
770
781
  createDeclaredSignalCell,
771
782
  createDerivedCellWith,
783
+ createDiagnosticLocalScope,
772
784
  createLocalScope,
773
785
  createResourceCellWith,
774
786
  createScope,
package/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = "0.4.1";
1
+ const version = "0.4.2";
2
2
  export {
3
3
  version
4
4
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "octane",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": [