11import { describe , expect , it , vi } from 'vitest'
2- import { atom , createStore } from 'jotai'
2+ import { type Atom , atom , createStore } from 'jotai'
33import type {
44 INTERNAL_AtomState ,
55 INTERNAL_AtomStateMap ,
@@ -15,6 +15,23 @@ import {
1515const buildingBlockLength = 29
1616
1717describe ( 'internals' , ( ) => {
18+ it ( 'every dependency (deep) should be mounted' , ( ) => {
19+ const depth = measureMaxSyncRecursionDepth ( )
20+ const mountedMap = new Map ( )
21+ const bb = [ ]
22+ bb [ 1 ] = mountedMap
23+ const store = INTERNAL_buildStore ( ...bb )
24+ const base = atom ( 0 )
25+ const chain : Atom < unknown > [ ] = [ base ]
26+ for ( let i = 0 ; i < depth ; i ++ ) {
27+ const parent = chain [ chain . length - 1 ] !
28+ chain . push ( atom ( ( get ) => get ( parent ) ) )
29+ }
30+ const leaf = chain [ chain . length - 1 ] !
31+ store . sub ( leaf , ( ) => { } )
32+ expect ( mountedMap . size ) . toBe ( depth )
33+ } )
34+
1835 it ( 'should not return a sparse building blocks array' , ( ) => {
1936 {
2037 const store = createStore ( )
@@ -331,3 +348,17 @@ function isBuildingBlocks(blocks: ReadonlyArray<unknown> | undefined) {
331348 isSparse ( blocks ) === false
332349 )
333350}
351+
352+ /** Deepest nested synchronous self-call before the engine throws (stack overflow). */
353+ function measureMaxSyncRecursionDepth ( ) : number {
354+ let max = 0
355+ const descend = ( n : number ) => {
356+ try {
357+ descend ( n + 1 )
358+ } catch {
359+ max = n
360+ }
361+ }
362+ descend ( 0 )
363+ return max
364+ }
0 commit comments