Skip to content

Commit

Permalink
Merge pull request #47 from kaytwo/main
Browse files Browse the repository at this point in the history
atomic persistentMap.set()
  • Loading branch information
ai authored Feb 21, 2024
2 parents 08a4185 + 495b893 commit 1833fcb
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 19 deletions.
17 changes: 12 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ let eventsEngine = { addEventListener() {}, removeEventListener() {} }
function testSupport() {
try {
return typeof localStorage !== 'undefined'
/* c8 ignore next 4 */
} catch {
/* c8 ignore next 3 */
// In Privacy Mode access to localStorage will return error
return false
}
Expand Down Expand Up @@ -89,7 +89,7 @@ export function persistentMap(prefix, initial = {}, opts = {}) {
let store = map()

let setKey = store.setKey
store.setKey = (key, newValue) => {
let storeKey = (key, newValue) => {
if (typeof newValue === 'undefined') {
if (opts.listen !== false && eventsEngine.perKey) {
eventsEngine.removeEventListener(prefix + key, listener, restore)
Expand All @@ -105,19 +105,24 @@ export function persistentMap(prefix, initial = {}, opts = {}) {
}
storageEngine[prefix + key] = encode(newValue)
}
}

store.setKey = (key, newValue) => {
storeKey(key, newValue)
setKey(key, newValue)
}

let set = store.set
store.set = function (newObject) {
for (let key in newObject) {
store.setKey(key, newObject[key])
storeKey(key, newObject[key])
}
for (let key in store.value) {
if (!(key in newObject)) {
store.setKey(key)
storeKey(key, undefined)
}
}
set(newObject)
}

function listener(e) {
Expand All @@ -139,7 +144,9 @@ export function persistentMap(prefix, initial = {}, opts = {}) {
data[key.slice(prefix.length)] = decode(storageEngine[key])
}
}
store.set(data)
for (let key in data) {
store.setKey(key, data[key])
}
}

onMount(store, () => {
Expand Down
55 changes: 41 additions & 14 deletions test/map.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import './setup.js'

import { delay } from 'nanodelay'
import { cleanStores, type MapStore } from 'nanostores'
import { cleanStores, type MapStore, map as nanoMap } from 'nanostores'
import { deepStrictEqual, equal } from 'node:assert'
import { afterEach, test } from 'node:test'

Expand Down Expand Up @@ -52,22 +52,11 @@ test('saves to localStorage', () => {

map.set({ one: '11' })
deepStrictEqual(localStorage, { 'b:one': '11' })
deepStrictEqual(events, [
{ one: '1' },
{ one: '1', two: '2' },
{ one: '11', two: '2' },
{ one: '11' }
])
deepStrictEqual(events, [{ one: '1' }, { one: '1', two: '2' }, { one: '11' }])

map.setKey('one', undefined)
deepStrictEqual(localStorage, {})
deepStrictEqual(events, [
{ one: '1' },
{ one: '1', two: '2' },
{ one: '11', two: '2' },
{ one: '11' },
{}
])
deepStrictEqual(events, [{ one: '1' }, { one: '1', two: '2' }, { one: '11' }, {}])
})

test('listens for other tabs', () => {
Expand Down Expand Up @@ -249,3 +238,41 @@ test('supports per key engine', async () => {
await delay(1010)
deepStrictEqual(Object.keys(listeners), [])
})

test('emits one event per update', () => {
map = persistentMap<{ one?: string; two?: string }>('1:', {
one: '1',
two: '2'
})

let events: object[] = []
map.listen(value => {
events.push(clone(value))
})
map.set({ one: '2', two: '3' })

equal(events.length, 1)
deepStrictEqual(map.get(), { one: '2', two: '3' })
})

test('emits equally many events per update compared to non-persistent map', () => {
map = persistentMap<{ one?: string; two?: string }>('1:', {
one: '1',
two: '2'
})
let nano = nanoMap({ one: '1', two: '2' })

let events: object[] = []
let nanoEvents: object[] = []
map.listen(value => {
events.push(clone(value))
})
nano.listen(value => {
nanoEvents.push(clone(value))
})
map.set({ one: '2', two: '3' })
nano.set({ one: '2', two: '3' })

deepStrictEqual(map.get(), nano.get())
equal(events.length, nanoEvents.length)
})

0 comments on commit 1833fcb

Please sign in to comment.