Skip to content

Commit 676d7b5

Browse files
committed
manage fields not immediately present in DOM
There are some cases where fields may not immediately be present in the DOM and added later (GitHub Slash Commands for instance). In these cases, when the fields are restored, those not present in the DOM are not restored (because they simply don't exist yet), however we completely remove all the stored fields' values from the session store. This means that fields that are added later will not have a change to restore their data. This change holds onto field values for fields that weren't able to be located in case that field is added to the DOM later and can then be restored. If a textarea never appears, it would stay in the session storage until the tab is closed. Because session storage is scoped to the tab, automatically cleared when the tab is closed, and has a 5 MB limit, this is unlikely to cause memory bloat problems.
1 parent 14feffc commit 676d7b5

2 files changed

Lines changed: 43 additions & 14 deletions

File tree

src/index.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,8 @@ export function restoreResumableFields(id: string, options?: RestoreOptions): vo
4646

4747
if (!fields) return
4848

49-
try {
50-
sessionStorage.removeItem(key)
51-
} catch {
52-
// Ignore browser private mode error.
53-
}
54-
5549
const changedFields: Array<HTMLInputElement | HTMLTextAreaElement> = []
50+
const storedFieldsNotFound: string[][] = []
5651

5752
for (const [fieldId, value] of JSON.parse(fields)) {
5853
const resumeEvent = new CustomEvent('session:resume', {
@@ -63,17 +58,30 @@ export function restoreResumableFields(id: string, options?: RestoreOptions): vo
6358

6459
if (document.dispatchEvent(resumeEvent)) {
6560
const field = document.getElementById(fieldId)
66-
if (
67-
field &&
68-
(field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement) &&
69-
field.value === field.defaultValue
70-
) {
71-
field.value = value
72-
changedFields.push(field)
61+
if (field && (field instanceof HTMLInputElement || field instanceof HTMLTextAreaElement)) {
62+
if (field.value === field.defaultValue) {
63+
field.value = value
64+
changedFields.push(field)
65+
}
66+
} else {
67+
storedFieldsNotFound.push([fieldId, value])
7368
}
7469
}
7570
}
7671

72+
// Some fields we want to restore are not always immediately present in the
73+
// DOM and may be added later. This holds onto the values until
74+
// they're needed.
75+
if (storedFieldsNotFound.length === 0) {
76+
try {
77+
sessionStorage.removeItem(key)
78+
} catch {
79+
// Ignore browser private mode error.
80+
}
81+
} else {
82+
sessionStorage.setItem(key, JSON.stringify(storedFieldsNotFound))
83+
}
84+
7785
setTimeout(function () {
7886
for (const el of changedFields) {
7987
el.dispatchEvent(new CustomEvent('change', {bubbles: true, cancelable: true}))

test/test.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,32 @@ describe('session-resume', function () {
1313

1414
describe('restoreResumableFields', function () {
1515
it('restores fields values from session storage', function () {
16-
sessionStorage.setItem('session-resume:test-persist', JSON.stringify([['my-first-field', 'test2']]))
16+
sessionStorage.setItem(
17+
'session-resume:test-persist',
18+
JSON.stringify([
19+
['my-first-field', 'test2'],
20+
['non-existant-field', 'test3']
21+
])
22+
)
1723
restoreResumableFields('test-persist')
1824

1925
assert.equal(document.querySelector('#my-first-field').value, 'test2')
2026
assert.equal(document.querySelector('#my-second-field').value, 'second-field-value')
27+
28+
// Some fields we want to restore are not always present in the DOM
29+
// and may be added later. We hold onto the values until they're needed.
30+
assert.deepEqual(JSON.parse(sessionStorage.getItem('session-resume:test-persist')), [
31+
['non-existant-field', 'test3']
32+
])
33+
})
34+
35+
it('removes the sessionStore key when all the fields were found', function () {
36+
sessionStorage.setItem('session-resume:test-persist', JSON.stringify([['my-first-field', 'test2']]))
37+
restoreResumableFields('test-persist')
38+
39+
// Some fields we want to restore are not always present in the DOM
40+
// and may be added later. We hold onto the values until they're needed.
41+
assert.equal(sessionStorage.getItem('session-resume:test-persist'), null)
2142
})
2243

2344
it('fires off session:resume events for changed fields', function () {

0 commit comments

Comments
 (0)