=> {
- const newSet = new Set(origSet)
- origSet.clear()
- return newSet
-}
-
const flushBatch = (batch: Batch) => {
let error: AnyError
let hasError = false
@@ -239,11 +233,14 @@ const flushBatch = (batch: Batch) => {
}
}
}
- while (batch.M.size || batch.L.size) {
+ while (batch.H.size || batch.M.size || batch.L.size) {
batch.D.clear()
- copySetAndClear(batch.H).forEach(call)
- copySetAndClear(batch.M).forEach(call)
- copySetAndClear(batch.L).forEach(call)
+ batch.H.forEach(call)
+ batch.H.clear()
+ batch.M.forEach(call)
+ batch.M.clear()
+ batch.L.forEach(call)
+ batch.L.clear()
}
if (hasError) {
throw error
diff --git a/tests/vanilla/store.test.tsx b/tests/vanilla/store.test.tsx
index ea6a97e019..5a186b0a3f 100644
--- a/tests/vanilla/store.test.tsx
+++ b/tests/vanilla/store.test.tsx
@@ -983,3 +983,25 @@ it('mounted atom should be recomputed eagerly', () => {
store.set(a, 1)
expect(result).toEqual(['bRead', 'aCallback', 'bCallback'])
})
+
+it('should process all atom listeners even if some of them throw errors', () => {
+ const store = createStore()
+ const a = atom(0)
+ const listenerA = vi.fn()
+ const listenerB = vi.fn(() => {
+ throw new Error('error')
+ })
+ const listenerC = vi.fn()
+
+ store.sub(a, listenerA)
+ store.sub(a, listenerB)
+ store.sub(a, listenerC)
+ try {
+ store.set(a, 1)
+ } catch {
+ // expect empty
+ }
+ expect(listenerA).toHaveBeenCalledTimes(1)
+ expect(listenerB).toHaveBeenCalledTimes(1)
+ expect(listenerC).toHaveBeenCalledTimes(1)
+})
diff --git a/tests/vanilla/storedev.test.tsx b/tests/vanilla/storedev.test.tsx
index 1771fafc28..15d5418fc0 100644
--- a/tests/vanilla/storedev.test.tsx
+++ b/tests/vanilla/storedev.test.tsx
@@ -7,7 +7,7 @@ import type {
describe('[DEV-ONLY] dev-only methods rev4', () => {
it('should get atom value', () => {
- const store = createStore() as any
+ const store = createStore() as INTERNAL_DevStoreRev4 & INTERNAL_PrdStore
if (!('dev4_get_internal_weak_map' in store)) {
throw new Error('dev methods are not available')
}
@@ -19,7 +19,7 @@ describe('[DEV-ONLY] dev-only methods rev4', () => {
})
it('should restore atoms and its dependencies correctly', () => {
- const store = createStore() as any
+ const store = createStore() as INTERNAL_DevStoreRev4 & INTERNAL_PrdStore
if (!('dev4_restore_atoms' in store)) {
throw new Error('dev methods are not available')
}
@@ -32,7 +32,7 @@ describe('[DEV-ONLY] dev-only methods rev4', () => {
})
it('should restore atoms and call store listeners correctly', () => {
- const store = createStore() as any
+ const store = createStore() as INTERNAL_DevStoreRev4 & INTERNAL_PrdStore
if (!('dev4_restore_atoms' in store)) {
throw new Error('dev methods are not available')
}
@@ -96,4 +96,14 @@ describe('[DEV-ONLY] dev-only methods rev4', () => {
const result = store.dev4_get_mounted_atoms()
expect(Array.from(result)).toStrictEqual([])
})
+
+ it('should restore atoms with custom write function', () => {
+ const store = createStore() as INTERNAL_DevStoreRev4 & INTERNAL_PrdStore
+ if (!('dev4_restore_atoms' in store)) {
+ throw new Error('dev methods are not available')
+ }
+ const countAtom = atom(0, () => {})
+ store.dev4_restore_atoms([[countAtom, 1]])
+ expect(store.get(countAtom)).toBe(1)
+ })
})
diff --git a/website/src/pages/index.js b/website/src/pages/index.js
index 6360c8c66f..bc92acfca9 100644
--- a/website/src/pages/index.js
+++ b/website/src/pages/index.js
@@ -118,7 +118,7 @@ const gettingStartedTabs = {
Installation
First add Jotai as a dependency to your React project.
{`# npm
-npm i jotai
+npm install jotai
# yarn
yarn add jotai