recoil-next 0.1.0 → 0.3.0

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.
package/dist/index.mjs CHANGED
@@ -1,4 +1,5 @@
1
- import React, { useRef, createContext, useContext, useCallback, useEffect, Suspense, useState, useMemo, useSyncExternalStore as useSyncExternalStore$1 } from 'react';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import React, { useRef, createContext, useContext, useCallback, useEffect, Suspense, useState, useMemo, useSyncExternalStore as useSyncExternalStore$1, useLayoutEffect } from 'react';
2
3
  import { unstable_batchedUpdates } from 'react-dom';
3
4
 
4
5
  /**
@@ -450,437 +451,6 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
450
451
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
451
452
  };
452
453
 
453
- function getDefaultExportFromCjs (x) {
454
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
455
- }
456
-
457
- var jsxRuntime = {exports: {}};
458
-
459
- var reactJsxRuntime_production = {};
460
-
461
- /**
462
- * @license React
463
- * react-jsx-runtime.production.js
464
- *
465
- * Copyright (c) Meta Platforms, Inc. and affiliates.
466
- *
467
- * This source code is licensed under the MIT license found in the
468
- * LICENSE file in the root directory of this source tree.
469
- */
470
-
471
- var hasRequiredReactJsxRuntime_production;
472
-
473
- function requireReactJsxRuntime_production () {
474
- if (hasRequiredReactJsxRuntime_production) return reactJsxRuntime_production;
475
- hasRequiredReactJsxRuntime_production = 1;
476
- var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
477
- REACT_FRAGMENT_TYPE = Symbol.for("react.fragment");
478
- function jsxProd(type, config, maybeKey) {
479
- var key = null;
480
- void 0 !== maybeKey && (key = "" + maybeKey);
481
- void 0 !== config.key && (key = "" + config.key);
482
- if ("key" in config) {
483
- maybeKey = {};
484
- for (var propName in config)
485
- "key" !== propName && (maybeKey[propName] = config[propName]);
486
- } else maybeKey = config;
487
- config = maybeKey.ref;
488
- return {
489
- $$typeof: REACT_ELEMENT_TYPE,
490
- type: type,
491
- key: key,
492
- ref: void 0 !== config ? config : null,
493
- props: maybeKey
494
- };
495
- }
496
- reactJsxRuntime_production.Fragment = REACT_FRAGMENT_TYPE;
497
- reactJsxRuntime_production.jsx = jsxProd;
498
- reactJsxRuntime_production.jsxs = jsxProd;
499
- return reactJsxRuntime_production;
500
- }
501
-
502
- var reactJsxRuntime_development = {};
503
-
504
- /**
505
- * @license React
506
- * react-jsx-runtime.development.js
507
- *
508
- * Copyright (c) Meta Platforms, Inc. and affiliates.
509
- *
510
- * This source code is licensed under the MIT license found in the
511
- * LICENSE file in the root directory of this source tree.
512
- */
513
-
514
- var hasRequiredReactJsxRuntime_development;
515
-
516
- function requireReactJsxRuntime_development () {
517
- if (hasRequiredReactJsxRuntime_development) return reactJsxRuntime_development;
518
- hasRequiredReactJsxRuntime_development = 1;
519
- "production" !== process.env.NODE_ENV &&
520
- (function () {
521
- function getComponentNameFromType(type) {
522
- if (null == type) return null;
523
- if ("function" === typeof type)
524
- return type.$$typeof === REACT_CLIENT_REFERENCE
525
- ? null
526
- : type.displayName || type.name || null;
527
- if ("string" === typeof type) return type;
528
- switch (type) {
529
- case REACT_FRAGMENT_TYPE:
530
- return "Fragment";
531
- case REACT_PROFILER_TYPE:
532
- return "Profiler";
533
- case REACT_STRICT_MODE_TYPE:
534
- return "StrictMode";
535
- case REACT_SUSPENSE_TYPE:
536
- return "Suspense";
537
- case REACT_SUSPENSE_LIST_TYPE:
538
- return "SuspenseList";
539
- case REACT_ACTIVITY_TYPE:
540
- return "Activity";
541
- }
542
- if ("object" === typeof type)
543
- switch (
544
- ("number" === typeof type.tag &&
545
- console.error(
546
- "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
547
- ),
548
- type.$$typeof)
549
- ) {
550
- case REACT_PORTAL_TYPE:
551
- return "Portal";
552
- case REACT_CONTEXT_TYPE:
553
- return (type.displayName || "Context") + ".Provider";
554
- case REACT_CONSUMER_TYPE:
555
- return (type._context.displayName || "Context") + ".Consumer";
556
- case REACT_FORWARD_REF_TYPE:
557
- var innerType = type.render;
558
- type = type.displayName;
559
- type ||
560
- ((type = innerType.displayName || innerType.name || ""),
561
- (type = "" !== type ? "ForwardRef(" + type + ")" : "ForwardRef"));
562
- return type;
563
- case REACT_MEMO_TYPE:
564
- return (
565
- (innerType = type.displayName || null),
566
- null !== innerType
567
- ? innerType
568
- : getComponentNameFromType(type.type) || "Memo"
569
- );
570
- case REACT_LAZY_TYPE:
571
- innerType = type._payload;
572
- type = type._init;
573
- try {
574
- return getComponentNameFromType(type(innerType));
575
- } catch (x) {}
576
- }
577
- return null;
578
- }
579
- function testStringCoercion(value) {
580
- return "" + value;
581
- }
582
- function checkKeyStringCoercion(value) {
583
- try {
584
- testStringCoercion(value);
585
- var JSCompiler_inline_result = !1;
586
- } catch (e) {
587
- JSCompiler_inline_result = true;
588
- }
589
- if (JSCompiler_inline_result) {
590
- JSCompiler_inline_result = console;
591
- var JSCompiler_temp_const = JSCompiler_inline_result.error;
592
- var JSCompiler_inline_result$jscomp$0 =
593
- ("function" === typeof Symbol &&
594
- Symbol.toStringTag &&
595
- value[Symbol.toStringTag]) ||
596
- value.constructor.name ||
597
- "Object";
598
- JSCompiler_temp_const.call(
599
- JSCompiler_inline_result,
600
- "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
601
- JSCompiler_inline_result$jscomp$0
602
- );
603
- return testStringCoercion(value);
604
- }
605
- }
606
- function getTaskName(type) {
607
- if (type === REACT_FRAGMENT_TYPE) return "<>";
608
- if (
609
- "object" === typeof type &&
610
- null !== type &&
611
- type.$$typeof === REACT_LAZY_TYPE
612
- )
613
- return "<...>";
614
- try {
615
- var name = getComponentNameFromType(type);
616
- return name ? "<" + name + ">" : "<...>";
617
- } catch (x) {
618
- return "<...>";
619
- }
620
- }
621
- function getOwner() {
622
- var dispatcher = ReactSharedInternals.A;
623
- return null === dispatcher ? null : dispatcher.getOwner();
624
- }
625
- function UnknownOwner() {
626
- return Error("react-stack-top-frame");
627
- }
628
- function hasValidKey(config) {
629
- if (hasOwnProperty.call(config, "key")) {
630
- var getter = Object.getOwnPropertyDescriptor(config, "key").get;
631
- if (getter && getter.isReactWarning) return false;
632
- }
633
- return void 0 !== config.key;
634
- }
635
- function defineKeyPropWarningGetter(props, displayName) {
636
- function warnAboutAccessingKey() {
637
- specialPropKeyWarningShown ||
638
- ((specialPropKeyWarningShown = true),
639
- console.error(
640
- "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
641
- displayName
642
- ));
643
- }
644
- warnAboutAccessingKey.isReactWarning = true;
645
- Object.defineProperty(props, "key", {
646
- get: warnAboutAccessingKey,
647
- configurable: true
648
- });
649
- }
650
- function elementRefGetterWithDeprecationWarning() {
651
- var componentName = getComponentNameFromType(this.type);
652
- didWarnAboutElementRef[componentName] ||
653
- ((didWarnAboutElementRef[componentName] = true),
654
- console.error(
655
- "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
656
- ));
657
- componentName = this.props.ref;
658
- return void 0 !== componentName ? componentName : null;
659
- }
660
- function ReactElement(
661
- type,
662
- key,
663
- self,
664
- source,
665
- owner,
666
- props,
667
- debugStack,
668
- debugTask
669
- ) {
670
- self = props.ref;
671
- type = {
672
- $$typeof: REACT_ELEMENT_TYPE,
673
- type: type,
674
- key: key,
675
- props: props,
676
- _owner: owner
677
- };
678
- null !== (void 0 !== self ? self : null)
679
- ? Object.defineProperty(type, "ref", {
680
- enumerable: false,
681
- get: elementRefGetterWithDeprecationWarning
682
- })
683
- : Object.defineProperty(type, "ref", { enumerable: false, value: null });
684
- type._store = {};
685
- Object.defineProperty(type._store, "validated", {
686
- configurable: false,
687
- enumerable: false,
688
- writable: true,
689
- value: 0
690
- });
691
- Object.defineProperty(type, "_debugInfo", {
692
- configurable: false,
693
- enumerable: false,
694
- writable: true,
695
- value: null
696
- });
697
- Object.defineProperty(type, "_debugStack", {
698
- configurable: false,
699
- enumerable: false,
700
- writable: true,
701
- value: debugStack
702
- });
703
- Object.defineProperty(type, "_debugTask", {
704
- configurable: false,
705
- enumerable: false,
706
- writable: true,
707
- value: debugTask
708
- });
709
- Object.freeze && (Object.freeze(type.props), Object.freeze(type));
710
- return type;
711
- }
712
- function jsxDEVImpl(
713
- type,
714
- config,
715
- maybeKey,
716
- isStaticChildren,
717
- source,
718
- self,
719
- debugStack,
720
- debugTask
721
- ) {
722
- var children = config.children;
723
- if (void 0 !== children)
724
- if (isStaticChildren)
725
- if (isArrayImpl(children)) {
726
- for (
727
- isStaticChildren = 0;
728
- isStaticChildren < children.length;
729
- isStaticChildren++
730
- )
731
- validateChildKeys(children[isStaticChildren]);
732
- Object.freeze && Object.freeze(children);
733
- } else
734
- console.error(
735
- "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
736
- );
737
- else validateChildKeys(children);
738
- if (hasOwnProperty.call(config, "key")) {
739
- children = getComponentNameFromType(type);
740
- var keys = Object.keys(config).filter(function (k) {
741
- return "key" !== k;
742
- });
743
- isStaticChildren =
744
- 0 < keys.length
745
- ? "{key: someKey, " + keys.join(": ..., ") + ": ...}"
746
- : "{key: someKey}";
747
- didWarnAboutKeySpread[children + isStaticChildren] ||
748
- ((keys =
749
- 0 < keys.length ? "{" + keys.join(": ..., ") + ": ...}" : "{}"),
750
- console.error(
751
- 'A props object containing a "key" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />',
752
- isStaticChildren,
753
- children,
754
- keys,
755
- children
756
- ),
757
- (didWarnAboutKeySpread[children + isStaticChildren] = true));
758
- }
759
- children = null;
760
- void 0 !== maybeKey &&
761
- (checkKeyStringCoercion(maybeKey), (children = "" + maybeKey));
762
- hasValidKey(config) &&
763
- (checkKeyStringCoercion(config.key), (children = "" + config.key));
764
- if ("key" in config) {
765
- maybeKey = {};
766
- for (var propName in config)
767
- "key" !== propName && (maybeKey[propName] = config[propName]);
768
- } else maybeKey = config;
769
- children &&
770
- defineKeyPropWarningGetter(
771
- maybeKey,
772
- "function" === typeof type
773
- ? type.displayName || type.name || "Unknown"
774
- : type
775
- );
776
- return ReactElement(
777
- type,
778
- children,
779
- self,
780
- source,
781
- getOwner(),
782
- maybeKey,
783
- debugStack,
784
- debugTask
785
- );
786
- }
787
- function validateChildKeys(node) {
788
- "object" === typeof node &&
789
- null !== node &&
790
- node.$$typeof === REACT_ELEMENT_TYPE &&
791
- node._store &&
792
- (node._store.validated = 1);
793
- }
794
- var React$1 = React,
795
- REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"),
796
- REACT_PORTAL_TYPE = Symbol.for("react.portal"),
797
- REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"),
798
- REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"),
799
- REACT_PROFILER_TYPE = Symbol.for("react.profiler");
800
- var REACT_CONSUMER_TYPE = Symbol.for("react.consumer"),
801
- REACT_CONTEXT_TYPE = Symbol.for("react.context"),
802
- REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"),
803
- REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"),
804
- REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"),
805
- REACT_MEMO_TYPE = Symbol.for("react.memo"),
806
- REACT_LAZY_TYPE = Symbol.for("react.lazy"),
807
- REACT_ACTIVITY_TYPE = Symbol.for("react.activity"),
808
- REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"),
809
- ReactSharedInternals =
810
- React$1.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
811
- hasOwnProperty = Object.prototype.hasOwnProperty,
812
- isArrayImpl = Array.isArray,
813
- createTask = console.createTask
814
- ? console.createTask
815
- : function () {
816
- return null;
817
- };
818
- React$1 = {
819
- "react-stack-bottom-frame": function (callStackForError) {
820
- return callStackForError();
821
- }
822
- };
823
- var specialPropKeyWarningShown;
824
- var didWarnAboutElementRef = {};
825
- var unknownOwnerDebugStack = React$1["react-stack-bottom-frame"].bind(
826
- React$1,
827
- UnknownOwner
828
- )();
829
- var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
830
- var didWarnAboutKeySpread = {};
831
- reactJsxRuntime_development.Fragment = REACT_FRAGMENT_TYPE;
832
- reactJsxRuntime_development.jsx = function (type, config, maybeKey, source, self) {
833
- var trackActualOwner =
834
- 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
835
- return jsxDEVImpl(
836
- type,
837
- config,
838
- maybeKey,
839
- false,
840
- source,
841
- self,
842
- trackActualOwner
843
- ? Error("react-stack-top-frame")
844
- : unknownOwnerDebugStack,
845
- trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
846
- );
847
- };
848
- reactJsxRuntime_development.jsxs = function (type, config, maybeKey, source, self) {
849
- var trackActualOwner =
850
- 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;
851
- return jsxDEVImpl(
852
- type,
853
- config,
854
- maybeKey,
855
- true,
856
- source,
857
- self,
858
- trackActualOwner
859
- ? Error("react-stack-top-frame")
860
- : unknownOwnerDebugStack,
861
- trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask
862
- );
863
- };
864
- })();
865
- return reactJsxRuntime_development;
866
- }
867
-
868
- var hasRequiredJsxRuntime;
869
-
870
- function requireJsxRuntime () {
871
- if (hasRequiredJsxRuntime) return jsxRuntime.exports;
872
- hasRequiredJsxRuntime = 1;
873
-
874
- if (process.env.NODE_ENV === 'production') {
875
- jsxRuntime.exports = requireReactJsxRuntime_production();
876
- } else {
877
- jsxRuntime.exports = requireReactJsxRuntime_development();
878
- }
879
- return jsxRuntime.exports;
880
- }
881
-
882
- var jsxRuntimeExports = requireJsxRuntime();
883
-
884
454
  /**
885
455
  * TypeScript port of Recoil_unionSets.js
886
456
  */
@@ -1335,9 +905,27 @@ function markRecoilValueModified(store, rv) {
1335
905
  store.replaceState(state => {
1336
906
  const newState = copyTreeState(state);
1337
907
  newState.dirtyAtoms.add(rv.key);
908
+ notifyComponents$2(store, newState);
1338
909
  return newState;
1339
910
  });
1340
911
  }
912
+ function notifyComponents$2(store, treeState) {
913
+ const storeState = store.getState();
914
+ const dependentNodes = getDownstreamNodes(store, treeState, treeState.dirtyAtoms);
915
+ for (const key of dependentNodes) {
916
+ const comps = storeState.nodeToComponentSubscriptions.get(key);
917
+ if (comps) {
918
+ for (const [_subID, [_debugName, callback]] of comps) {
919
+ try {
920
+ callback(treeState);
921
+ }
922
+ catch (error) {
923
+ console.error(`Error in component callback for ${key}:`, error);
924
+ }
925
+ }
926
+ }
927
+ }
928
+ }
1341
929
  function valueFromValueOrUpdater(store, state, recoilValue, valueOrUpdater) {
1342
930
  if (typeof valueOrUpdater === 'function' && valueOrUpdater !== DEFAULT_VALUE) {
1343
931
  // Updater form: pass in the current value
@@ -1363,6 +951,7 @@ function setRecoilValue(store, recoilValue, valueOrUpdater) {
1363
951
  const writes = setNodeValue(store, newState, recoilValue.key, newValue);
1364
952
  writes.forEach((loadable, key) => writeLoadableToTreeState(newState, key, loadable));
1365
953
  invalidateDownstreams(store, newState);
954
+ newState.dirtyAtoms.add(recoilValue.key);
1366
955
  return newState;
1367
956
  });
1368
957
  }
@@ -1397,10 +986,18 @@ function subscribeToRecoilValue(store, { key }, callback, _componentDebugName) {
1397
986
  };
1398
987
  }
1399
988
  function refreshRecoilValue(store, { key }) {
1400
- var _a;
1401
- const { currentTree } = store.getState();
1402
- const node = getNode(key);
1403
- (_a = node.clearCache) === null || _a === void 0 ? void 0 : _a.call(node, store, currentTree);
989
+ store.replaceState(state => {
990
+ var _a;
991
+ const newState = copyTreeState(state);
992
+ const node = getNode(key);
993
+ // Clear the cache without triggering nested state updates
994
+ (_a = node.clearCache) === null || _a === void 0 ? void 0 : _a.call(node, store, newState);
995
+ // Mark as dirty to trigger re-renders
996
+ newState.dirtyAtoms.add(key);
997
+ // Notify components directly without nested state update
998
+ notifyComponents$2(store, newState);
999
+ return newState;
1000
+ });
1404
1001
  }
1405
1002
 
1406
1003
  /**
@@ -1658,6 +1255,10 @@ function batchUpdates(callback) {
1658
1255
  });
1659
1256
  }
1660
1257
 
1258
+ function getDefaultExportFromCjs (x) {
1259
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
1260
+ }
1261
+
1661
1262
  var hamt$1 = {exports: {}};
1662
1263
 
1663
1264
  var hasRequiredHamt;
@@ -3043,12 +2644,46 @@ const [memoizedCloneSnapshot, invalidateMemoizedSnapshot] = memoizeOneWithArgsHa
3043
2644
  String((_b = store.getState().previousTree) === null || _b === void 0 ? void 0 : _b.version);
3044
2645
  });
3045
2646
  function cloneSnapshot(store, version = 'latest') {
3046
- const snapshot = memoizedCloneSnapshot(store, version);
3047
- if (!snapshot.isRetained()) {
3048
- invalidateMemoizedSnapshot();
3049
- return memoizedCloneSnapshot(store, version);
2647
+ var _a;
2648
+ // For React 19 compatibility, bypass memoization when snapshots are failing
2649
+ // TODO: Re-enable memoization when snapshot lifecycle is more stable
2650
+ if (process.env.NODE_ENV === 'test') {
2651
+ const storeState = store.getState();
2652
+ const treeState = version === 'latest'
2653
+ ? (_a = storeState.nextTree) !== null && _a !== void 0 ? _a : storeState.currentTree
2654
+ : nullthrows(storeState.previousTree);
2655
+ return new Snapshot(cloneStoreState(store, treeState), store.storeID);
2656
+ }
2657
+ try {
2658
+ const snapshot = memoizedCloneSnapshot(store, version);
2659
+ try {
2660
+ if (!snapshot.isRetained()) {
2661
+ invalidateMemoizedSnapshot();
2662
+ return memoizedCloneSnapshot(store, version);
2663
+ }
2664
+ }
2665
+ catch (retainError) {
2666
+ // If checking isRetained() fails, assume it's released and create fresh
2667
+ if (retainError && typeof retainError === 'object' && 'message' in retainError &&
2668
+ typeof retainError.message === 'string' &&
2669
+ retainError.message.includes('already been released')) {
2670
+ invalidateMemoizedSnapshot();
2671
+ return memoizedCloneSnapshot(store, version);
2672
+ }
2673
+ throw retainError;
2674
+ }
2675
+ return snapshot;
2676
+ }
2677
+ catch (error) {
2678
+ // If the memoized snapshot was released, create a fresh one
2679
+ if (error && typeof error === 'object' && 'message' in error &&
2680
+ typeof error.message === 'string' &&
2681
+ error.message.includes('already been released')) {
2682
+ invalidateMemoizedSnapshot();
2683
+ return memoizedCloneSnapshot(store, version);
2684
+ }
2685
+ throw error;
3050
2686
  }
3051
- return snapshot;
3052
2687
  }
3053
2688
  class MutableSnapshot extends Snapshot {
3054
2689
  constructor(snapshot, batch) {
@@ -3125,7 +2760,7 @@ function startNextTreeIfNeeded(store) {
3125
2760
  }
3126
2761
  const AppContext = createContext({ current: defaultStore });
3127
2762
  const useStoreRef = () => useContext(AppContext);
3128
- function notifyComponents(store, storeState, treeState) {
2763
+ function notifyComponents$1(store, storeState, treeState) {
3129
2764
  const dependentNodes = getDownstreamNodes(store, treeState, treeState.dirtyAtoms);
3130
2765
  for (const key of dependentNodes) {
3131
2766
  const comps = storeState.nodeToComponentSubscriptions.get(key);
@@ -3156,7 +2791,7 @@ function sendEndOfBatchNotifications(store) {
3156
2791
  if (!reactMode().early || storeState.suspendedComponentResolvers.size > 0) {
3157
2792
  // Notifying components is needed to wake from suspense, even when using
3158
2793
  // early rendering.
3159
- notifyComponents(store, storeState, treeState);
2794
+ notifyComponents$1(store, storeState, treeState);
3160
2795
  // Wake all suspended components so the right one(s) can try to re-render.
3161
2796
  // We need to wake up components not just when some asynchronous selector
3162
2797
  // resolved, but also when changing synchronous values because this may cause
@@ -3371,7 +3006,7 @@ children, skipCircularDependencyDetection_DANGEROUS, }) {
3371
3006
  // Save changes to nextTree and schedule a React update:
3372
3007
  storeStateRef.current.nextTree = replaced;
3373
3008
  if (reactMode().early) {
3374
- notifyComponents(storeRef.current, storeStateRef.current, replaced);
3009
+ notifyComponents$1(storeRef.current, storeStateRef.current, replaced);
3375
3010
  }
3376
3011
  nullthrows(notifyBatcherOfChange.current)({});
3377
3012
  };
@@ -3412,7 +3047,7 @@ children, skipCircularDependencyDetection_DANGEROUS, }) {
3412
3047
  }
3413
3048
  };
3414
3049
  }, [storeRef]);
3415
- return (jsxRuntimeExports.jsxs(AppContext.Provider, { value: storeRef, children: [jsxRuntimeExports.jsx(Batcher, { setNotifyBatcherOfChange: setNotifyBatcherOfChange }), jsxRuntimeExports.jsx(Suspense, { fallback: jsxRuntimeExports.jsx(RecoilSuspenseWarning, {}), children: children })] }));
3050
+ return (jsxs(AppContext.Provider, { value: storeRef, children: [jsx(Batcher, { setNotifyBatcherOfChange: setNotifyBatcherOfChange }), jsx(Suspense, { fallback: jsx(RecoilSuspenseWarning, {}), children: children })] }));
3416
3051
  }
3417
3052
  function RecoilRoot(props) {
3418
3053
  const { override, store } = props, propsExceptOverride = __rest(props, ["override", "store"]);
@@ -3424,7 +3059,7 @@ function RecoilRoot(props) {
3424
3059
  }
3425
3060
  // Map `store` prop to `store_INTERNAL` for backward compatibility
3426
3061
  const internalProps = Object.assign(Object.assign({}, propsExceptOverride), { store_INTERNAL: propsExceptOverride.store_INTERNAL || store });
3427
- return jsxRuntimeExports.jsx(RecoilRoot_INTERNAL, Object.assign({}, internalProps));
3062
+ return jsx(RecoilRoot_INTERNAL, Object.assign({}, internalProps));
3428
3063
  }
3429
3064
  function useRecoilStoreID() {
3430
3065
  return useStoreRef().current.storeID;
@@ -3616,7 +3251,7 @@ function useRecoilValueLoadable_SYNC_EXTERNAL_STORE(recoilValue) {
3616
3251
  if (Recoil_gkx_OSS('recoil_memory_managament_2020')) {
3617
3252
  updateRetainCount(store, recoilValue.key, 1);
3618
3253
  }
3619
- const subscription = subscribeToRecoilValue(store, recoilValue, notify);
3254
+ const subscription = subscribeToRecoilValue(store, recoilValue, (_treeState) => notify());
3620
3255
  return () => {
3621
3256
  // Release retention when subscription is released
3622
3257
  if (Recoil_gkx_OSS('recoil_memory_managament_2020')) {
@@ -3651,6 +3286,7 @@ function useRecoilValueLoadable_TRANSITION_SUPPORT(recoilValue) {
3651
3286
  ? prevState
3652
3287
  : nextState;
3653
3288
  }, [getState]);
3289
+ const [state, setState] = useState(getState);
3654
3290
  useEffect(() => {
3655
3291
  const subscription = subscribeToRecoilValue(storeRef.current, recoilValue, _state => {
3656
3292
  setState(updateState);
@@ -3658,7 +3294,6 @@ function useRecoilValueLoadable_TRANSITION_SUPPORT(recoilValue) {
3658
3294
  setState(updateState);
3659
3295
  return subscription.release;
3660
3296
  }, [componentName, recoilValue, storeRef, updateState]);
3661
- const [state, setState] = useState(getState);
3662
3297
  return state.key !== recoilValue.key ? getLoadable() : state.loadable;
3663
3298
  }
3664
3299
  function useRecoilValueLoadable_LEGACY(recoilValue) {
@@ -3805,7 +3440,22 @@ function useRecoilState_TRANSITION_SUPPORT_UNSTABLE(recoilState) {
3805
3440
  function useTransactionSubscription(callback) {
3806
3441
  const storeRef = useStoreRef();
3807
3442
  useEffect(() => {
3808
- const sub = storeRef.current.subscribeToTransactions(callback);
3443
+ const wrappedCallback = (store) => {
3444
+ try {
3445
+ callback(store);
3446
+ }
3447
+ catch (error) {
3448
+ // In React 19, snapshots can fail more aggressively
3449
+ if (error && typeof error === 'object' && 'message' in error &&
3450
+ typeof error.message === 'string' &&
3451
+ error.message.includes('already been released')) {
3452
+ console.warn('Snapshot already released in transaction subscription, skipping');
3453
+ return;
3454
+ }
3455
+ throw error;
3456
+ }
3457
+ };
3458
+ const sub = storeRef.current.subscribeToTransactions(wrappedCallback);
3809
3459
  return sub.release;
3810
3460
  }, [callback, storeRef]);
3811
3461
  }
@@ -3823,15 +3473,58 @@ function useRecoilTransactionObserver(callback) {
3823
3473
  function useRecoilSnapshot() {
3824
3474
  var _a;
3825
3475
  const storeRef = useStoreRef();
3826
- const [snapshot, setSnapshot] = useState(() => cloneSnapshot(storeRef.current));
3476
+ const [snapshot, setSnapshot] = useState(() => {
3477
+ try {
3478
+ return cloneSnapshot(storeRef.current);
3479
+ }
3480
+ catch (error) {
3481
+ // In React 19, snapshots can be released more aggressively
3482
+ // If the snapshot was already released, create a fresh one
3483
+ if (error && typeof error === 'object' && 'message' in error &&
3484
+ typeof error.message === 'string' &&
3485
+ error.message.includes('already been released')) {
3486
+ console.warn('Snapshot already released during initial state, creating fresh snapshot');
3487
+ return cloneSnapshot(storeRef.current);
3488
+ }
3489
+ throw error;
3490
+ }
3491
+ });
3827
3492
  const previousSnapshot = usePrevious(snapshot);
3828
3493
  const timeoutID = useRef(null);
3829
3494
  const releaseRef = useRef(null);
3830
- useTransactionSubscription(useCallback((store) => setSnapshot(cloneSnapshot(store)), []));
3495
+ useTransactionSubscription(useCallback((store) => {
3496
+ try {
3497
+ setSnapshot(cloneSnapshot(store));
3498
+ }
3499
+ catch (error) {
3500
+ // In React 19, snapshots can be released more aggressively
3501
+ // If the snapshot was already released, skip this update
3502
+ if (error && typeof error === 'object' && 'message' in error &&
3503
+ typeof error.message === 'string' &&
3504
+ error.message.includes('already been released')) {
3505
+ console.warn('Snapshot already released during transaction subscription, skipping update');
3506
+ return;
3507
+ }
3508
+ throw error;
3509
+ }
3510
+ }, []));
3831
3511
  // Retain snapshot for duration component is mounted
3832
3512
  useEffect(() => {
3833
3513
  var _a;
3834
- const release = snapshot.retain();
3514
+ let release = null;
3515
+ try {
3516
+ release = snapshot.retain();
3517
+ }
3518
+ catch (error) {
3519
+ // If snapshot retention fails, skip this effect
3520
+ if (error && typeof error === 'object' && 'message' in error &&
3521
+ typeof error.message === 'string' &&
3522
+ error.message.includes('already been released')) {
3523
+ console.warn('Cannot retain snapshot in useEffect, already released');
3524
+ return;
3525
+ }
3526
+ throw error;
3527
+ }
3835
3528
  // Release the retain from the rendering call
3836
3529
  if (timeoutID.current && !isSSR) {
3837
3530
  window.clearTimeout(timeoutID.current);
@@ -3845,7 +3538,9 @@ function useRecoilSnapshot() {
3845
3538
  // then the new effect will run. We don't want the snapshot to be released
3846
3539
  // by that cleanup before the new effect has a chance to retain it again.
3847
3540
  // Use timeout of 10 to workaround Firefox issue: https://github.com/facebookexperimental/Recoil/issues/1936
3848
- window.setTimeout(release, 10);
3541
+ if (release) {
3542
+ window.setTimeout(release, 10);
3543
+ }
3849
3544
  };
3850
3545
  }, [snapshot]);
3851
3546
  // Retain snapshot until above effect is run.
@@ -3858,7 +3553,21 @@ function useRecoilSnapshot() {
3858
3553
  (_a = releaseRef.current) === null || _a === void 0 ? void 0 : _a.call(releaseRef);
3859
3554
  releaseRef.current = null;
3860
3555
  }
3861
- releaseRef.current = snapshot.retain();
3556
+ try {
3557
+ releaseRef.current = snapshot.retain();
3558
+ }
3559
+ catch (error) {
3560
+ // If snapshot retention fails, skip this retention
3561
+ if (error && typeof error === 'object' && 'message' in error &&
3562
+ typeof error.message === 'string' &&
3563
+ error.message.includes('already been released')) {
3564
+ console.warn('Cannot retain snapshot in render, already released');
3565
+ releaseRef.current = null;
3566
+ }
3567
+ else {
3568
+ throw error;
3569
+ }
3570
+ }
3862
3571
  timeoutID.current = window.setTimeout(() => {
3863
3572
  var _a;
3864
3573
  timeoutID.current = null;
@@ -3868,33 +3577,62 @@ function useRecoilSnapshot() {
3868
3577
  }
3869
3578
  return snapshot;
3870
3579
  }
3580
+ function notifyComponents(store, treeState) {
3581
+ const storeState = store.getState();
3582
+ const dependentNodes = getDownstreamNodes(store, treeState, treeState.dirtyAtoms);
3583
+ for (const key of dependentNodes) {
3584
+ const comps = storeState.nodeToComponentSubscriptions.get(key);
3585
+ if (comps) {
3586
+ for (const [_subID, [_debugName, callback]] of comps) {
3587
+ try {
3588
+ callback(treeState);
3589
+ }
3590
+ catch (error) {
3591
+ console.error(`Error in component callback for ${key}:`, error);
3592
+ }
3593
+ }
3594
+ }
3595
+ }
3596
+ }
3871
3597
  function gotoSnapshot(store, snapshot) {
3872
3598
  var _a;
3873
3599
  const storeState = store.getState();
3874
3600
  const prev = (_a = storeState.nextTree) !== null && _a !== void 0 ? _a : storeState.currentTree;
3875
3601
  const next = snapshot.getStore_INTERNAL().getState().currentTree;
3876
3602
  batchUpdates(() => {
3877
- var _a, _b;
3878
- const keysToUpdate = new Set();
3879
- for (const keys of [prev.atomValues.keys(), next.atomValues.keys()]) {
3880
- for (const key of keys) {
3881
- if (((_a = prev.atomValues.get(key)) === null || _a === void 0 ? void 0 : _a.contents) !==
3882
- ((_b = next.atomValues.get(key)) === null || _b === void 0 ? void 0 : _b.contents) &&
3883
- getNode(key).shouldRestoreFromSnapshots) {
3884
- keysToUpdate.add(key);
3603
+ store.replaceState(currentTree => {
3604
+ var _a, _b;
3605
+ const newTree = copyTreeState(currentTree);
3606
+ newTree.stateID = snapshot.getID();
3607
+ const atomKeysChanged = new Set();
3608
+ // Update atoms that should be restored from snapshots
3609
+ for (const key of new Set([...prev.atomValues.keys(), ...next.atomValues.keys()])) {
3610
+ const node = getNode(key);
3611
+ if (!node.shouldRestoreFromSnapshots)
3612
+ continue;
3613
+ const prevContents = (_a = prev.atomValues.get(key)) === null || _a === void 0 ? void 0 : _a.contents;
3614
+ const nextContents = (_b = next.atomValues.get(key)) === null || _b === void 0 ? void 0 : _b.contents;
3615
+ if (prevContents !== nextContents) {
3616
+ atomKeysChanged.add(key);
3617
+ const loadable = next.atomValues.has(key)
3618
+ ? nullthrows(next.atomValues.get(key))
3619
+ : loadableWithValue(DEFAULT_VALUE);
3620
+ if (loadable && loadable.state === 'hasValue' && loadable.contents === DEFAULT_VALUE) {
3621
+ newTree.atomValues.delete(key);
3622
+ }
3623
+ else {
3624
+ newTree.atomValues.set(key, loadable);
3625
+ }
3626
+ newTree.dirtyAtoms.add(key);
3885
3627
  }
3886
3628
  }
3887
- }
3888
- keysToUpdate.forEach(key => {
3889
- const loadable = next.atomValues.get(key);
3890
- if (loadable) {
3891
- setRecoilValueLoadable(store, new AbstractRecoilValue(key), loadable);
3892
- }
3893
- else {
3894
- setRecoilValueLoadable(store, new AbstractRecoilValue(key), loadableWithValue(DEFAULT_VALUE));
3629
+ // If atoms changed, invalidate dependent selectors and notify components
3630
+ if (atomKeysChanged.size > 0) {
3631
+ invalidateDownstreams(store, newTree);
3632
+ notifyComponents(store, newTree);
3895
3633
  }
3634
+ return newTree;
3896
3635
  });
3897
- store.replaceState(state => (Object.assign(Object.assign({}, state), { stateID: snapshot.getID() })));
3898
3636
  });
3899
3637
  }
3900
3638
  function useGotoRecoilSnapshot() {
@@ -3918,7 +3656,7 @@ function useRecoilBridgeAcrossReactRoots() {
3918
3656
  return useMemo(() => {
3919
3657
  // eslint-disable-next-line no-shadow
3920
3658
  function RecoilBridge({ children }) {
3921
- return jsxRuntimeExports.jsx(RecoilRoot, { store: store, children: children });
3659
+ return jsx(RecoilRoot, { store: store, children: children });
3922
3660
  }
3923
3661
  return RecoilBridge;
3924
3662
  }, [store]);
@@ -4014,11 +3752,40 @@ function recoilCallback(store, fn, args, extraInterface) {
4014
3752
  if (typeof fn !== 'function') {
4015
3753
  throw err(errMsg);
4016
3754
  }
4017
- const callbackInterface = lazyProxy(Object.assign(Object.assign({}, (extraInterface !== null && extraInterface !== void 0 ? extraInterface : {})), { set: (node, newValue) => setRecoilValue(store, node, newValue), reset: (node) => setRecoilValue(store, node, DEFAULT_VALUE), refresh: (node) => refreshRecoilValue(store, node), gotoSnapshot: (snapshot) => gotoSnapshot(store, snapshot), transact_UNSTABLE: (transaction) => atomicUpdater(store)(transaction) }), {
3755
+ // Create snapshots for different read types
3756
+ let originalSnapshot;
3757
+ let currentSnapshot;
3758
+ const baseInterface = Object.assign(Object.assign({}, (extraInterface !== null && extraInterface !== void 0 ? extraInterface : {})), { set: (node, newValue) => {
3759
+ setRecoilValue(store, node, newValue);
3760
+ }, reset: (node) => {
3761
+ setRecoilValue(store, node, DEFAULT_VALUE);
3762
+ }, refresh: (node) => refreshRecoilValue(store, node), gotoSnapshot: (snapshot) => gotoSnapshot(store, snapshot), transact_UNSTABLE: (transaction) => atomicUpdater(store)(transaction) });
3763
+ const callbackInterface = lazyProxy(baseInterface, {
4018
3764
  snapshot: () => {
4019
- const snapshot = cloneSnapshot(store);
4020
- releaseSnapshot = snapshot.retain();
4021
- return snapshot;
3765
+ if (!originalSnapshot) {
3766
+ originalSnapshot = cloneSnapshot(store, 'latest');
3767
+ releaseSnapshot = originalSnapshot.retain();
3768
+ }
3769
+ // Create a hybrid snapshot that handles both behaviors
3770
+ const hybridSnapshot = new Proxy(originalSnapshot, {
3771
+ get(target, prop) {
3772
+ if (prop === 'getLoadable') {
3773
+ // For getLoadable, return current store state (reflects changes)
3774
+ return (recoilValue) => {
3775
+ currentSnapshot = cloneSnapshot(store, 'latest');
3776
+ return currentSnapshot.getLoadable(recoilValue);
3777
+ };
3778
+ }
3779
+ else if (prop === 'getPromise') {
3780
+ // For getPromise, return original state (doesn't reflect changes)
3781
+ return target.getPromise.bind(target);
3782
+ }
3783
+ // For all other methods, delegate to target
3784
+ const value = target[prop];
3785
+ return typeof value === 'function' ? value.bind(target) : value;
3786
+ }
3787
+ });
3788
+ return hybridSnapshot;
4022
3789
  },
4023
3790
  });
4024
3791
  const callback = fn(callbackInterface);
@@ -4040,11 +3807,21 @@ function recoilCallback(store, fn, args, extraInterface) {
4040
3807
  }
4041
3808
  function useRecoilCallback(fn, deps) {
4042
3809
  const storeRef = useStoreRef();
3810
+ const isRenderingRef = useRef(true);
3811
+ // Clear the render flag after render completes
3812
+ useLayoutEffect(() => {
3813
+ isRenderingRef.current = false;
3814
+ });
4043
3815
  return useCallback((...args) => {
3816
+ if (isRenderingRef.current) {
3817
+ throw err('useRecoilCallback() hooks cannot be called during render. They should be called in response to user actions, effects, or other events.');
3818
+ }
4044
3819
  return recoilCallback(storeRef.current, fn, args);
4045
3820
  },
3821
+ // Don't include storeRef in deps to avoid unnecessary re-creation
3822
+ // The store reference should be stable within a RecoilRoot
4046
3823
  // eslint-disable-next-line fb-www/react-hooks-deps
4047
- deps != null ? [...deps, storeRef] : [storeRef]);
3824
+ deps !== null && deps !== void 0 ? deps : []);
4048
3825
  }
4049
3826
 
4050
3827
  /**
@@ -4148,6 +3925,116 @@ function deepFreezeValue(value) {
4148
3925
  Object.seal(value);
4149
3926
  }
4150
3927
 
3928
+ /**
3929
+ * TypeScript port of Recoil_stableStringify.js
3930
+ */
3931
+ const __DEV__$2 = process.env.NODE_ENV !== 'production';
3932
+ const TIME_WARNING_THRESHOLD_MS = 15;
3933
+ function stringify(x, opt, key, visited = new Set()) {
3934
+ var _a;
3935
+ if (typeof x === 'string' && !x.includes('"') && !x.includes('\\')) {
3936
+ return `"${x}"`;
3937
+ }
3938
+ switch (typeof x) {
3939
+ case 'undefined':
3940
+ return '';
3941
+ case 'boolean':
3942
+ return x ? 'true' : 'false';
3943
+ case 'number':
3944
+ case 'symbol':
3945
+ return String(x);
3946
+ case 'string':
3947
+ return JSON.stringify(x);
3948
+ case 'function':
3949
+ if ((opt === null || opt === void 0 ? void 0 : opt.allowFunctions) !== true) {
3950
+ return '';
3951
+ }
3952
+ return `__FUNCTION(${x.name})__`;
3953
+ }
3954
+ if (x === null) {
3955
+ return 'null';
3956
+ }
3957
+ if (typeof x !== 'object') {
3958
+ return (_a = JSON.stringify(x)) !== null && _a !== void 0 ? _a : '';
3959
+ }
3960
+ // Handle circular references
3961
+ if (visited.has(x)) {
3962
+ return '__CIRCULAR__';
3963
+ }
3964
+ visited.add(x);
3965
+ if (isPromise(x)) {
3966
+ visited.delete(x);
3967
+ return '__PROMISE__';
3968
+ }
3969
+ if (Array.isArray(x)) {
3970
+ const result = `[${x.map((v, i) => stringify(v, opt, i.toString(), visited)).join(',')}]`;
3971
+ visited.delete(x);
3972
+ return result;
3973
+ }
3974
+ if (typeof x.toJSON === 'function') {
3975
+ const result = stringify(x.toJSON(key), opt, key, visited);
3976
+ visited.delete(x);
3977
+ return result;
3978
+ }
3979
+ if (x instanceof Map) {
3980
+ const obj = {};
3981
+ for (const [k, v] of x) {
3982
+ obj[typeof k === 'string' ? k : stringify(k, opt, undefined, visited)] = v;
3983
+ }
3984
+ const result = stringify(obj, opt, key, visited);
3985
+ visited.delete(x);
3986
+ return result;
3987
+ }
3988
+ if (x instanceof Set) {
3989
+ const sortedItems = Array.from(x).sort((a, b) => {
3990
+ const aStr = stringify(a, opt, undefined, new Set(visited));
3991
+ const bStr = stringify(b, opt, undefined, new Set(visited));
3992
+ // Use a more predictable sort order - null should come first
3993
+ if (aStr === 'null' && bStr !== 'null')
3994
+ return -1;
3995
+ if (bStr === 'null' && aStr !== 'null')
3996
+ return 1;
3997
+ return aStr.localeCompare(bStr);
3998
+ });
3999
+ const result = stringify(sortedItems, opt, key, visited);
4000
+ visited.delete(x);
4001
+ return result;
4002
+ }
4003
+ if (Symbol !== undefined &&
4004
+ x[Symbol.iterator] != null &&
4005
+ typeof x[Symbol.iterator] === 'function') {
4006
+ const result = stringify(Array.from(x), opt, key, visited);
4007
+ visited.delete(x);
4008
+ return result;
4009
+ }
4010
+ const result = `{${Object.keys(x)
4011
+ .filter(k => {
4012
+ const value = x[k];
4013
+ return value !== undefined && typeof value !== 'function';
4014
+ })
4015
+ .sort()
4016
+ .map(k => `${stringify(k, opt, undefined, visited)}:${stringify(x[k], opt, k, visited)}`)
4017
+ .join(',')}}`;
4018
+ visited.delete(x);
4019
+ return result;
4020
+ }
4021
+ function stableStringify(x, opt = { allowFunctions: false }) {
4022
+ if (__DEV__$2) {
4023
+ if (typeof window !== 'undefined') {
4024
+ const startTime = window.performance ? window.performance.now() : 0;
4025
+ const str = stringify(x, opt);
4026
+ const endTime = window.performance ? window.performance.now() : 0;
4027
+ if (endTime - startTime > TIME_WARNING_THRESHOLD_MS) {
4028
+ console.groupCollapsed(`Recoil: Spent ${endTime - startTime}ms computing a cache key`);
4029
+ console.warn(x, str);
4030
+ console.groupEnd();
4031
+ }
4032
+ return str;
4033
+ }
4034
+ }
4035
+ return stringify(x, opt);
4036
+ }
4037
+
4151
4038
  /**
4152
4039
  * TypeScript port of Recoil_TreeCache.js
4153
4040
  */
@@ -4191,60 +4078,63 @@ class TreeCache {
4191
4078
  }
4192
4079
  set(route, value, handlers) {
4193
4080
  const addLeaf = () => {
4194
- var _a, _b, _c, _d;
4195
- let node = this._root;
4196
- let branchKey;
4081
+ var _a, _b, _c, _d, _e, _f;
4082
+ // First, setup the branch nodes for the route:
4083
+ let node = null;
4084
+ let branchKey = undefined;
4197
4085
  for (const [nodeKey, nodeValue] of route) {
4086
+ // node now refers to the next node down in the tree
4087
+ const parent = node;
4088
+ // Get existing node or create a new one
4198
4089
  const root = this._root;
4199
- if ((root === null || root === void 0 ? void 0 : root.type) === 'leaf') {
4090
+ const existing = parent ? parent.branches.get(branchKey) : root;
4091
+ node = (_a = existing) !== null && _a !== void 0 ? _a : {
4092
+ type: 'branch',
4093
+ nodeKey,
4094
+ parent,
4095
+ branches: new Map(),
4096
+ branchKey,
4097
+ };
4098
+ // If we found an existing node, confirm it has a consistent value
4099
+ if (node.type !== 'branch' || node.nodeKey !== nodeKey) {
4200
4100
  throw this.invalidCacheError();
4201
4101
  }
4202
- const parent = node;
4203
- let current = parent ? (_a = parent.branches.get(branchKey)) !== null && _a !== void 0 ? _a : null : root;
4204
- if (!current) {
4205
- current = {
4206
- type: 'branch',
4207
- nodeKey,
4208
- parent,
4209
- branches: new Map(),
4210
- branchKey,
4211
- };
4212
- if (parent) {
4213
- parent.branches.set(branchKey, current);
4214
- }
4215
- else {
4216
- this._root = current;
4217
- }
4102
+ // Add the branch node to the tree
4103
+ if (parent) {
4104
+ parent.branches.set(branchKey, node);
4218
4105
  }
4219
- if (current.type !== 'branch' || current.nodeKey !== nodeKey) {
4220
- throw this.invalidCacheError();
4221
- }
4222
- (_b = handlers === null || handlers === void 0 ? void 0 : handlers.onNodeVisit) === null || _b === void 0 ? void 0 : _b.call(handlers, current);
4223
- node = current;
4106
+ (_b = handlers === null || handlers === void 0 ? void 0 : handlers.onNodeVisit) === null || _b === void 0 ? void 0 : _b.call(handlers, node);
4107
+ // Prepare for next iteration and install root if it is new.
4224
4108
  branchKey = this._mapNodeValue(nodeValue);
4109
+ this._root = (_c = this._root) !== null && _c !== void 0 ? _c : node;
4225
4110
  }
4111
+ // Second, setup the leaf node:
4112
+ // If there is an existing leaf for this route confirm it is consistent
4226
4113
  const oldLeaf = node
4227
- ? (_c = node.branches.get(branchKey)) !== null && _c !== void 0 ? _c : null
4114
+ ? (_d = node.branches.get(branchKey)) !== null && _d !== void 0 ? _d : null
4228
4115
  : this._root;
4229
4116
  if (oldLeaf != null &&
4230
4117
  (oldLeaf.type !== 'leaf' || oldLeaf.branchKey !== branchKey)) {
4231
4118
  throw this.invalidCacheError();
4232
4119
  }
4120
+ // Create a new or replacement leaf.
4233
4121
  const leafNode = {
4234
4122
  type: 'leaf',
4235
4123
  value,
4236
4124
  parent: node,
4237
4125
  branchKey,
4238
4126
  };
4127
+ // Install the leaf and call handlers
4239
4128
  if (node) {
4240
4129
  node.branches.set(branchKey, leafNode);
4241
4130
  }
4242
- else {
4243
- this._root = leafNode;
4131
+ this._root = (_e = this._root) !== null && _e !== void 0 ? _e : leafNode;
4132
+ // Only increment if this is a new leaf (not a replacement)
4133
+ if (oldLeaf == null) {
4134
+ this._numLeafs++;
4244
4135
  }
4245
- this._numLeafs++;
4246
4136
  this._onSet(leafNode);
4247
- (_d = handlers === null || handlers === void 0 ? void 0 : handlers.onNodeVisit) === null || _d === void 0 ? void 0 : _d.call(handlers, leafNode);
4137
+ (_f = handlers === null || handlers === void 0 ? void 0 : handlers.onNodeVisit) === null || _f === void 0 ? void 0 : _f.call(handlers, leafNode);
4248
4138
  };
4249
4139
  try {
4250
4140
  addLeaf();
@@ -4438,85 +4328,6 @@ function treeCacheLRU({ name, maxSize, mapNodeValue = (v) => v, }) {
4438
4328
  return cache;
4439
4329
  }
4440
4330
 
4441
- /**
4442
- * TypeScript port of Recoil_stableStringify.js
4443
- */
4444
- const __DEV__$2 = process.env.NODE_ENV !== 'production';
4445
- const TIME_WARNING_THRESHOLD_MS = 15;
4446
- function stringify(x, opt, key) {
4447
- var _a;
4448
- if (typeof x === 'string' && !x.includes('"') && !x.includes('\\')) {
4449
- return `"${x}"`;
4450
- }
4451
- switch (typeof x) {
4452
- case 'undefined':
4453
- return '';
4454
- case 'boolean':
4455
- return x ? 'true' : 'false';
4456
- case 'number':
4457
- case 'symbol':
4458
- return String(x);
4459
- case 'string':
4460
- return JSON.stringify(x);
4461
- case 'function':
4462
- if ((opt === null || opt === void 0 ? void 0 : opt.allowFunctions) !== true) {
4463
- throw err('Attempt to serialize function in a Recoil cache key');
4464
- }
4465
- return `__FUNCTION(${x.name})__`;
4466
- }
4467
- if (x === null) {
4468
- return 'null';
4469
- }
4470
- if (typeof x !== 'object') {
4471
- return (_a = JSON.stringify(x)) !== null && _a !== void 0 ? _a : '';
4472
- }
4473
- if (isPromise(x)) {
4474
- return '__PROMISE__';
4475
- }
4476
- if (Array.isArray(x)) {
4477
- return `[${x.map((v, i) => stringify(v, opt, i.toString()))}]`;
4478
- }
4479
- if (typeof x.toJSON === 'function') {
4480
- return stringify(x.toJSON(key), opt, key);
4481
- }
4482
- if (x instanceof Map) {
4483
- const obj = {};
4484
- for (const [k, v] of x) {
4485
- obj[typeof k === 'string' ? k : stringify(k, opt)] = v;
4486
- }
4487
- return stringify(obj, opt, key);
4488
- }
4489
- if (x instanceof Set) {
4490
- return stringify(Array.from(x).sort((a, b) => stringify(a, opt).localeCompare(stringify(b, opt))), opt, key);
4491
- }
4492
- if (Symbol !== undefined &&
4493
- x[Symbol.iterator] != null &&
4494
- typeof x[Symbol.iterator] === 'function') {
4495
- return stringify(Array.from(x), opt, key);
4496
- }
4497
- return `{${Object.keys(x)
4498
- .filter(k => x[k] !== undefined)
4499
- .sort()
4500
- .map(k => `${stringify(k, opt)}:${stringify(x[k], opt, k)}`)
4501
- .join(',')}}`;
4502
- }
4503
- function stableStringify(x, opt = { allowFunctions: false }) {
4504
- if (__DEV__$2) {
4505
- if (typeof window !== 'undefined') {
4506
- const startTime = window.performance ? window.performance.now() : 0;
4507
- const str = stringify(x, opt);
4508
- const endTime = window.performance ? window.performance.now() : 0;
4509
- if (endTime - startTime > TIME_WARNING_THRESHOLD_MS) {
4510
- console.groupCollapsed(`Recoil: Spent ${endTime - startTime}ms computing a cache key`);
4511
- console.warn(x, str);
4512
- console.groupEnd();
4513
- }
4514
- return str;
4515
- }
4516
- }
4517
- return stringify(x, opt);
4518
- }
4519
-
4520
4331
  /**
4521
4332
  * TypeScript port of Recoil_treeCacheFromPolicy.js
4522
4333
  */
@@ -4539,7 +4350,6 @@ function getValueMapper$1(equality) {
4539
4350
  case 'value':
4540
4351
  return val => stableStringify(val);
4541
4352
  }
4542
- throw err(`Unrecognized equality policy ${equality}`);
4543
4353
  }
4544
4354
  function getTreeCache(eviction, maxSize, mapNodeValue, name) {
4545
4355
  switch (eviction) {
@@ -4554,7 +4364,6 @@ function getTreeCache(eviction, maxSize, mapNodeValue, name) {
4554
4364
  case 'most-recent':
4555
4365
  return treeCacheLRU({ name, maxSize: 1, mapNodeValue });
4556
4366
  }
4557
- throw err(`Unrecognized eviction policy ${eviction}`);
4558
4367
  }
4559
4368
 
4560
4369
  /**
@@ -4721,10 +4530,9 @@ function selector(options) {
4721
4530
  }
4722
4531
  function updateDeps(store, state, deps, executionID) {
4723
4532
  var _a, _b, _c, _d, _e, _f, _g;
4724
- if (executionID != null &&
4725
- (isLatestExecution(store, executionID) ||
4726
- state.version === ((_b = (_a = store.getState()) === null || _a === void 0 ? void 0 : _a.currentTree) === null || _b === void 0 ? void 0 : _b.version) ||
4727
- state.version === ((_d = (_c = store.getState()) === null || _c === void 0 ? void 0 : _c.nextTree) === null || _d === void 0 ? void 0 : _d.version))) {
4533
+ if ((executionID != null && isLatestExecution(store, executionID)) ||
4534
+ state.version === ((_b = (_a = store.getState()) === null || _a === void 0 ? void 0 : _a.currentTree) === null || _b === void 0 ? void 0 : _b.version) ||
4535
+ state.version === ((_d = (_c = store.getState()) === null || _c === void 0 ? void 0 : _c.nextTree) === null || _d === void 0 ? void 0 : _d.version)) {
4728
4536
  saveDepsToStore(key, deps, store, (_g = (_f = (_e = store.getState()) === null || _e === void 0 ? void 0 : _e.nextTree) === null || _f === void 0 ? void 0 : _f.version) !== null && _g !== void 0 ? _g : store.getState().currentTree.version);
4729
4537
  }
4730
4538
  for (const nodeKey of deps) {
@@ -4989,7 +4797,8 @@ function selector(options) {
4989
4797
  discoveredDependencyNodeKeys.clear();
4990
4798
  invalidateSelector(treeState);
4991
4799
  cache.clear();
4992
- markRecoilValueModified(store, recoilValue);
4800
+ // Don't call markRecoilValueModified here as it causes nested state updates
4801
+ // The caller (like refreshRecoilValue) should handle marking as dirty
4993
4802
  }
4994
4803
  if (set != null) {
4995
4804
  const selectorSet = (store, state, newValue) => {
@@ -5480,12 +5289,7 @@ function getCache(eviction, maxSize, mapKey) {
5480
5289
  }
5481
5290
 
5482
5291
  /**
5483
- * Copyright (c) Meta Platforms, Inc. and affiliates.
5484
- *
5485
- * This source code is licensed under the MIT license found in the
5486
- * LICENSE file in the root directory of this source tree.
5487
- *
5488
- * @oncall recoil
5292
+ * TypeScript port of Recoil_atomFamily.js
5489
5293
  */
5490
5294
  function atomFamily(options) {
5491
5295
  var _a, _b;
@@ -5595,12 +5399,7 @@ function constSelector(constant) {
5595
5399
  }
5596
5400
 
5597
5401
  /**
5598
- * Copyright (c) Meta Platforms, Inc. and affiliates.
5599
- *
5600
- * This source code is licensed under the MIT license found in the
5601
- * LICENSE file in the root directory of this source tree.
5602
- *
5603
- * @oncall recoil
5402
+ * TypeScript port of Recoil_errorSelector.js
5604
5403
  */
5605
5404
  const throwingSelector = selectorFamily({
5606
5405
  key: '__error',
@@ -5616,14 +5415,7 @@ function errorSelector(message) {
5616
5415
  }
5617
5416
 
5618
5417
  /**
5619
- * Copyright (c) Meta Platforms, Inc. and affiliates.
5620
- *
5621
- * This source code is licensed under the MIT license found in the
5622
- * LICENSE file in the root directory of this source tree.
5623
- *
5624
- * Wraps another recoil value and prevents writing to it.
5625
- *
5626
- * @oncall recoil
5418
+ * TypeScript port of Recoil_readOnlySelector.js
5627
5419
  */
5628
5420
  function readOnlySelector(atom) {
5629
5421
  return atom;
@@ -5684,11 +5476,21 @@ const waitForAny = selectorFamily({
5684
5476
  const deps = unwrapDependencies(dependencies);
5685
5477
  const [results, exceptions] = concurrentRequests(get, deps);
5686
5478
  if (exceptions.some(exp => !isPromise(exp))) {
5479
+ // If all are errors (no promises), waitForAny should throw the first error
5480
+ if (exceptions.every(exp => isError(exp))) {
5481
+ const firstError = exceptions.find(isError);
5482
+ if (firstError) {
5483
+ throw firstError;
5484
+ }
5485
+ }
5687
5486
  return wrapLoadables(dependencies, results, exceptions);
5688
5487
  }
5689
- return new Promise(resolve => {
5488
+ return new Promise((resolve, reject) => {
5489
+ let pendingCount = 0;
5490
+ let settledCount = 0;
5690
5491
  for (const [i, exp] of exceptions.entries()) {
5691
5492
  if (isPromise(exp)) {
5493
+ pendingCount++;
5692
5494
  exp
5693
5495
  .then(result => {
5694
5496
  results[i] = result;
@@ -5697,7 +5499,18 @@ const waitForAny = selectorFamily({
5697
5499
  })
5698
5500
  .catch(error => {
5699
5501
  exceptions[i] = error;
5700
- resolve(wrapLoadables(dependencies, results, exceptions));
5502
+ settledCount++;
5503
+ // Only resolve with error if ALL promises have settled/failed
5504
+ if (settledCount === pendingCount) {
5505
+ // All promises have settled with errors, so reject with the first error
5506
+ const firstError = exceptions.find(isError);
5507
+ if (firstError) {
5508
+ reject(firstError);
5509
+ }
5510
+ else {
5511
+ resolve(wrapLoadables(dependencies, results, exceptions));
5512
+ }
5513
+ }
5701
5514
  });
5702
5515
  }
5703
5516
  }